@abaplint/transpiler-cli 2.13.100 → 2.14.1
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 +89 -1
- package/build/bundle.js +923 -235
- package/build/types.d.ts +6 -0
- package/package.json +3 -3
- package/schema.json +42 -0
- 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, config.skip_duplicate_dependencies);
|
|
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,276 @@ 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, skipDuplicateDependencies = false) {
|
|
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
|
+
const skipped = new Set();
|
|
570
|
+
for (const file of lib.files) {
|
|
571
|
+
const memory = new abaplint.MemoryFile(file.filename, file.contents);
|
|
572
|
+
const type = memory.getObjectType()?.toUpperCase();
|
|
573
|
+
if (type === undefined || file.filename.split(".").length <= 2) {
|
|
574
|
+
continue;
|
|
575
|
+
}
|
|
576
|
+
const key = type + ":" + memory.getObjectName().toUpperCase();
|
|
577
|
+
const owner = objects.get(key);
|
|
578
|
+
// abapGit repeats package.devc.xml across repositories; the registry keeps the last copy.
|
|
579
|
+
if (key !== "DEVC:PACKAGE" && owner !== undefined && owner !== lib.name) {
|
|
580
|
+
if (skipDuplicateDependencies === true) {
|
|
581
|
+
if (!skipped.has(key)) {
|
|
582
|
+
console.warn("Skipping duplicate dependency object " + key + " in " + lib.name + "; using " + owner);
|
|
583
|
+
skipped.add(key);
|
|
584
|
+
}
|
|
585
|
+
// Skip every file of the losing object, including locals, metadata, and binary assets.
|
|
586
|
+
continue;
|
|
587
|
+
}
|
|
588
|
+
throw new Error("Ambiguous dependency object " + key + " in " + owner + " and " + lib.name);
|
|
589
|
+
}
|
|
590
|
+
objects.set(key, lib.name);
|
|
591
|
+
reg.addDependency(memory);
|
|
592
|
+
folders.set(file.filename.toLowerCase(), lib.name);
|
|
593
|
+
sources.set(file.filename.toLowerCase(), file);
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
for (const file of files) {
|
|
597
|
+
reg.addFile(new abaplint.MemoryFile(file.filename, file.contents));
|
|
598
|
+
folders.set(file.filename.toLowerCase(), "project");
|
|
599
|
+
sources.set(file.filename.toLowerCase(), file);
|
|
600
|
+
}
|
|
601
|
+
return { reg, folders, sources: [...sources.values()] };
|
|
602
|
+
}
|
|
603
|
+
//# sourceMappingURL=libraries.js.map
|
|
604
|
+
|
|
605
|
+
/***/ },
|
|
606
|
+
|
|
607
|
+
/***/ "./build/write_objects.js"
|
|
608
|
+
/*!********************************!*\
|
|
609
|
+
!*** ./build/write_objects.js ***!
|
|
610
|
+
\********************************/
|
|
611
|
+
(__unused_webpack_module, exports, __webpack_require__) {
|
|
612
|
+
|
|
613
|
+
"use strict";
|
|
614
|
+
|
|
615
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
616
|
+
if (k2 === undefined) k2 = k;
|
|
617
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
618
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
619
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
620
|
+
}
|
|
621
|
+
Object.defineProperty(o, k2, desc);
|
|
622
|
+
}) : (function(o, m, k, k2) {
|
|
623
|
+
if (k2 === undefined) k2 = k;
|
|
624
|
+
o[k2] = m[k];
|
|
625
|
+
}));
|
|
626
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
627
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
628
|
+
}) : function(o, v) {
|
|
629
|
+
o["default"] = v;
|
|
630
|
+
});
|
|
631
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
632
|
+
var ownKeys = function(o) {
|
|
633
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
634
|
+
var ar = [];
|
|
635
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
636
|
+
return ar;
|
|
637
|
+
};
|
|
638
|
+
return ownKeys(o);
|
|
639
|
+
};
|
|
640
|
+
return function (mod) {
|
|
641
|
+
if (mod && mod.__esModule) return mod;
|
|
642
|
+
var result = {};
|
|
643
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
644
|
+
__setModuleDefault(result, mod);
|
|
645
|
+
return result;
|
|
646
|
+
};
|
|
647
|
+
})();
|
|
648
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
649
|
+
exports.writeObjects = writeObjects;
|
|
650
|
+
const path = __importStar(__webpack_require__(/*! path */ "path"));
|
|
651
|
+
const url_1 = __webpack_require__(/*! url */ "url");
|
|
652
|
+
const transpiler_1 = __webpack_require__(/*! @abaplint/transpiler */ "./node_modules/@abaplint/transpiler/build/src/index.js");
|
|
653
|
+
const file_operations_1 = __webpack_require__(/*! ./file_operations */ "./build/file_operations.js");
|
|
654
|
+
async function writeObjects(outputFiles, config, files) {
|
|
655
|
+
const root = path.resolve(config.output_folder);
|
|
656
|
+
const filesToWrite = [];
|
|
657
|
+
const destinations = new Set();
|
|
658
|
+
const sources = new Map(files.map(file => [file.filename.toLowerCase(), file]));
|
|
659
|
+
const add = (filename, contents) => {
|
|
660
|
+
const target = path.resolve(root, filename);
|
|
661
|
+
const relative = path.relative(root, target);
|
|
662
|
+
if (relative === "" || relative.startsWith(".." + path.sep) || relative === ".." || path.isAbsolute(relative)) {
|
|
663
|
+
throw new Error("Output file escapes output_folder: " + filename);
|
|
664
|
+
}
|
|
665
|
+
const key = target.toLowerCase();
|
|
666
|
+
if (destinations.has(key)) {
|
|
667
|
+
throw new Error("Conflicting output file: " + filename);
|
|
668
|
+
}
|
|
669
|
+
destinations.add(key);
|
|
670
|
+
filesToWrite.push({ path: target, contents });
|
|
671
|
+
};
|
|
672
|
+
for (const output of outputFiles) {
|
|
673
|
+
const type = output.object.type.toUpperCase();
|
|
674
|
+
let contents = output.chunk.getCode();
|
|
675
|
+
let generatedLineOffset = 0;
|
|
676
|
+
if (type === "PROG") {
|
|
677
|
+
contents = 'if (!globalThis.abap) await import("' + (0, transpiler_1.importPath)(output.filename, "_init.mjs") + '");\n' + contents;
|
|
678
|
+
generatedLineOffset = 1;
|
|
679
|
+
}
|
|
680
|
+
if (config.write_source_map === true && (type === "PROG" || type === "FUGR" || type === "CLAS")) {
|
|
681
|
+
const name = output.filename + ".map";
|
|
682
|
+
contents += "\n//# sourceMappingURL=" + encodeURIComponent(path.basename(name));
|
|
683
|
+
const sourcePaths = {};
|
|
684
|
+
const sourceContents = {};
|
|
685
|
+
const mapDirectory = path.dirname(path.join(root, name));
|
|
686
|
+
for (const filename of new Set(output.chunk.mappings.map(mapping => mapping.source))) {
|
|
687
|
+
const file = sources.get(filename.toLowerCase());
|
|
688
|
+
if (file === undefined) {
|
|
689
|
+
continue;
|
|
690
|
+
}
|
|
691
|
+
if (file.relative !== undefined) {
|
|
692
|
+
const source = path.resolve(root, file.relative, file.filename);
|
|
693
|
+
const relative = path.relative(mapDirectory, source);
|
|
694
|
+
// Sources on another Windows drive cannot be expressed as relative paths.
|
|
695
|
+
sourcePaths[filename] = path.isAbsolute(relative) ? (0, url_1.pathToFileURL)(source).href
|
|
696
|
+
: relative.split(path.sep).map(segment => encodeURIComponent(segment)).join("/");
|
|
697
|
+
}
|
|
698
|
+
// Include sources for local and cloned libraries; clones are removed before emission.
|
|
699
|
+
sourceContents[filename] = file.contents;
|
|
700
|
+
}
|
|
701
|
+
add(name, output.chunk.getMap(path.basename(output.filename), { generatedLineOffset, sourcePaths, sourceContents }));
|
|
702
|
+
}
|
|
703
|
+
add(output.filename, contents);
|
|
704
|
+
}
|
|
705
|
+
await file_operations_1.FileOperations.writeFiles(filesToWrite);
|
|
706
|
+
}
|
|
707
|
+
//# sourceMappingURL=write_objects.js.map
|
|
708
|
+
|
|
709
|
+
/***/ },
|
|
710
|
+
|
|
556
711
|
/***/ "./node_modules/@abaplint/core/build/src/abap/1_lexer/lexer.js"
|
|
557
712
|
/*!*********************************************************************!*\
|
|
558
713
|
!*** ./node_modules/@abaplint/core/build/src/abap/1_lexer/lexer.js ***!
|
|
@@ -10941,7 +11096,7 @@ class StringTemplateFormatting extends combi_1.Expression {
|
|
|
10941
11096
|
const alpha = (0, combi_1.ver)(version_1.Release.v740sp02, (0, combi_1.seq)("ALPHA =", alphaOptions), { also: combi_1.AlsoIn.OpenABAP });
|
|
10942
11097
|
const xsd = (0, combi_1.ver)(version_1.Release.v740sp02, (0, combi_1.seq)("XSD =", zeroXSDOptions));
|
|
10943
11098
|
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)("
|
|
11099
|
+
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
11100
|
return formatting;
|
|
10946
11101
|
}
|
|
10947
11102
|
}
|
|
@@ -30673,12 +30828,15 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
30673
30828
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
30674
30829
|
exports.Compare = void 0;
|
|
30675
30830
|
const Expressions = __importStar(__webpack_require__(/*! ../../2_statements/expressions */ "./node_modules/@abaplint/core/build/src/abap/2_statements/expressions/index.js"));
|
|
30831
|
+
const nodes_1 = __webpack_require__(/*! ../../nodes */ "./node_modules/@abaplint/core/build/src/abap/nodes/index.js");
|
|
30676
30832
|
const source_1 = __webpack_require__(/*! ./source */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/source.js");
|
|
30677
30833
|
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
30834
|
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
30835
|
const _syntax_input_1 = __webpack_require__(/*! ../_syntax_input */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/_syntax_input.js");
|
|
30680
30836
|
const basic_1 = __webpack_require__(/*! ../../types/basic */ "./node_modules/@abaplint/core/build/src/abap/types/basic/index.js");
|
|
30681
30837
|
const _type_utils_1 = __webpack_require__(/*! ../_type_utils */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/_type_utils.js");
|
|
30838
|
+
const _builtin_1 = __webpack_require__(/*! ../_builtin */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/_builtin.js");
|
|
30839
|
+
const _object_oriented_1 = __webpack_require__(/*! ../_object_oriented */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/_object_oriented.js");
|
|
30682
30840
|
class Compare {
|
|
30683
30841
|
static runSyntax(node, input) {
|
|
30684
30842
|
var _a;
|
|
@@ -30693,6 +30851,11 @@ class Compare {
|
|
|
30693
30851
|
for (const t of node.findDirectExpressions(Expressions.MethodCallChain)) {
|
|
30694
30852
|
method_call_chain_1.MethodCallChain.runSyntax(t, input);
|
|
30695
30853
|
}
|
|
30854
|
+
const initialMessage = this.checkInitialOperand(node, input);
|
|
30855
|
+
if (initialMessage !== undefined) {
|
|
30856
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), initialMessage));
|
|
30857
|
+
return;
|
|
30858
|
+
}
|
|
30696
30859
|
const typeUtils = new _type_utils_1.TypeUtils(input.scope);
|
|
30697
30860
|
const compareOperator = (_a = node.findDirectExpression(Expressions.CompareOperator)) === null || _a === void 0 ? void 0 : _a.concatTokens().toUpperCase();
|
|
30698
30861
|
if (compareOperator === "CS"
|
|
@@ -30716,6 +30879,46 @@ class Compare {
|
|
|
30716
30879
|
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
|
|
30717
30880
|
}
|
|
30718
30881
|
}
|
|
30882
|
+
// a built-in function with a character-like result cannot be the operand of IS [NOT] INITIAL,
|
|
30883
|
+
// "Unexpected operator IS" on a system, while one with a numeric result, lines( ), can
|
|
30884
|
+
static checkInitialOperand(node, input) {
|
|
30885
|
+
var _a, _b, _c, _d;
|
|
30886
|
+
if (input.scope.getOpenABAP()) {
|
|
30887
|
+
return undefined;
|
|
30888
|
+
}
|
|
30889
|
+
const tokens = node.getChildren().filter(c => c instanceof nodes_1.TokenNode).map(c => c.getFirstToken().getStr().toUpperCase());
|
|
30890
|
+
if (tokens.includes("IS") === false || tokens[tokens.length - 1] !== "INITIAL") {
|
|
30891
|
+
return undefined;
|
|
30892
|
+
}
|
|
30893
|
+
const chain = (_a = node.findDirectExpression(Expressions.Source)) === null || _a === void 0 ? void 0 : _a.getChildren();
|
|
30894
|
+
// xsdbool( ) and boolc( ) are their own form in the Source grammar, a condition in parentheses
|
|
30895
|
+
const first = (_b = chain === null || chain === void 0 ? void 0 : chain[0]) === null || _b === void 0 ? void 0 : _b.getFirstToken().getStr().toUpperCase();
|
|
30896
|
+
if ((chain === null || chain === void 0 ? void 0 : chain.length) === 4 && chain[0] instanceof nodes_1.TokenNode && (first === "XSDBOOL" || first === "BOOLC")) {
|
|
30897
|
+
return `Built-in function "${chain[0].getFirstToken().getStr()}" cannot be the operand of IS INITIAL`;
|
|
30898
|
+
}
|
|
30899
|
+
if ((chain === null || chain === void 0 ? void 0 : chain.length) !== 1 || !(chain[0] instanceof nodes_1.ExpressionNode) || !(chain[0].get() instanceof Expressions.MethodCallChain)) {
|
|
30900
|
+
return undefined;
|
|
30901
|
+
}
|
|
30902
|
+
const calls = chain[0].getChildren();
|
|
30903
|
+
if (calls.length !== 1 || !(calls[0] instanceof nodes_1.ExpressionNode) || !(calls[0].get() instanceof Expressions.MethodCall)) {
|
|
30904
|
+
return undefined;
|
|
30905
|
+
}
|
|
30906
|
+
const name = (_c = calls[0].findDirectExpression(Expressions.MethodName)) === null || _c === void 0 ? void 0 : _c.concatTokens();
|
|
30907
|
+
const builtin = _builtin_1.BuiltIn.searchBuiltin(name);
|
|
30908
|
+
if (name === undefined || builtin === undefined) {
|
|
30909
|
+
return undefined;
|
|
30910
|
+
}
|
|
30911
|
+
// a method of the same name hides the built-in function
|
|
30912
|
+
const enclosing = input.scope.findClassDefinition(input.scope.getEnclosingClassName());
|
|
30913
|
+
if (enclosing !== undefined && new _object_oriented_1.ObjectOriented(input.scope).searchMethodName(enclosing, name).method !== undefined) {
|
|
30914
|
+
return undefined;
|
|
30915
|
+
}
|
|
30916
|
+
const returning = (_d = builtin.getParameters().getReturning()) === null || _d === void 0 ? void 0 : _d.getType();
|
|
30917
|
+
if (returning instanceof basic_1.StringType || returning instanceof basic_1.CharacterType) {
|
|
30918
|
+
return `Built-in function "${name}" cannot be the operand of IS INITIAL`;
|
|
30919
|
+
}
|
|
30920
|
+
return undefined;
|
|
30921
|
+
}
|
|
30719
30922
|
}
|
|
30720
30923
|
exports.Compare = Compare;
|
|
30721
30924
|
//# sourceMappingURL=compare.js.map
|
|
@@ -71077,7 +71280,7 @@ class Registry {
|
|
|
71077
71280
|
}
|
|
71078
71281
|
static abaplintVersion() {
|
|
71079
71282
|
// magic, see build script "version.js"
|
|
71080
|
-
return "2.120.
|
|
71283
|
+
return "2.120.71";
|
|
71081
71284
|
}
|
|
71082
71285
|
getDDICReferences() {
|
|
71083
71286
|
return this.ddicReferences;
|
|
@@ -73766,7 +73969,7 @@ exports.CDSCheckSyntaxConf = CDSCheckSyntaxConf;
|
|
|
73766
73969
|
const KNOWN_QUAN_DATA_ELEMENTS = ["MENGE_D"];
|
|
73767
73970
|
const KNOWN_CURR_DATA_ELEMENTS = ["BWERT", "DZWERT"];
|
|
73768
73971
|
// Reserved names, cannot be used as element names, see DDIC table TRESE
|
|
73769
|
-
const RESERVED_ELEMENT_NAMES = ["BEGIN", "NUMBER", "POSITION"];
|
|
73972
|
+
const RESERVED_ELEMENT_NAMES = ["BEGIN", "NUMBER", "POSITION", "ZONE", "HANDLER", "SECTION"];
|
|
73770
73973
|
const MAX_LABEL_LENGTH = 40;
|
|
73771
73974
|
// Annotations which are not supported in CDS view entities
|
|
73772
73975
|
const VIEW_ENTITY_FORBIDDEN_ANNOTATIONS = ["Semantics.unitOfMeasure", "Semantics.currencyCode"];
|
|
@@ -95476,7 +95679,8 @@ class RedundantConversion {
|
|
|
95476
95679
|
key: "redundant_conversion",
|
|
95477
95680
|
title: "Redundant Conversion",
|
|
95478
95681
|
shortDescription: `Find redundant CONV expressions`,
|
|
95479
|
-
extendedInformation: `Reports CONV expressions whose operand already has the conversion's target type
|
|
95682
|
+
extendedInformation: `Reports CONV expressions whose operand already has the conversion's target type,
|
|
95683
|
+
including the result of a built-in function with a fixed result type, like to_upper( ) or strlen( ).`,
|
|
95480
95684
|
tags: [_irule_1.RuleTag.Quickfix],
|
|
95481
95685
|
badExample: `DATA text TYPE string.
|
|
95482
95686
|
text = CONV string( text ).`,
|
|
@@ -95513,7 +95717,8 @@ text = text.`,
|
|
|
95513
95717
|
if (structure === undefined) {
|
|
95514
95718
|
continue;
|
|
95515
95719
|
}
|
|
95516
|
-
|
|
95720
|
+
// recursive, a CONV can be the argument of a built-in function, which is itself a Source
|
|
95721
|
+
for (const source of structure.findAllExpressionsRecursive(Expressions.Source)) {
|
|
95517
95722
|
if (source.getFirstToken().getStr().toUpperCase() !== "CONV") {
|
|
95518
95723
|
continue;
|
|
95519
95724
|
}
|
|
@@ -95572,6 +95777,15 @@ text = text.`,
|
|
|
95572
95777
|
}
|
|
95573
95778
|
sourceType(source, scope) {
|
|
95574
95779
|
let context;
|
|
95780
|
+
// boolc( <condition> ) is not a MethodCallChain, xsdbool( ) has the same shape but is not reported
|
|
95781
|
+
const first = source.getFirstToken();
|
|
95782
|
+
if (first.getStr().toUpperCase() === "BOOLC"
|
|
95783
|
+
&& source.findDirectExpression(Expressions.Cond) !== undefined
|
|
95784
|
+
&& source.getChildren().length === 4
|
|
95785
|
+
&& scope.getData().references.some(reference => reference.referenceType === _reference_1.ReferenceType.BuiltinMethodReference
|
|
95786
|
+
&& reference.position.getStart().equals(first.getStart()))) {
|
|
95787
|
+
return basic_1.StringType.get();
|
|
95788
|
+
}
|
|
95575
95789
|
for (const child of source.getChildren()) {
|
|
95576
95790
|
if (!(child instanceof nodes_1.ExpressionNode)) {
|
|
95577
95791
|
continue;
|
|
@@ -95582,6 +95796,15 @@ text = text.`,
|
|
|
95582
95796
|
return undefined;
|
|
95583
95797
|
}
|
|
95584
95798
|
}
|
|
95799
|
+
else if (child.get() instanceof Expressions.MethodCallChain) {
|
|
95800
|
+
if (source.getChildren().length !== 1) {
|
|
95801
|
+
return undefined;
|
|
95802
|
+
}
|
|
95803
|
+
context = this.builtinResultType(child, scope);
|
|
95804
|
+
if (context === undefined) {
|
|
95805
|
+
return undefined;
|
|
95806
|
+
}
|
|
95807
|
+
}
|
|
95585
95808
|
else if (child.get() instanceof Expressions.Constant) {
|
|
95586
95809
|
context = this.infer(context, constant_1.Constant.runSyntax(child));
|
|
95587
95810
|
}
|
|
@@ -95602,6 +95825,32 @@ text = text.`,
|
|
|
95602
95825
|
}
|
|
95603
95826
|
return context;
|
|
95604
95827
|
}
|
|
95828
|
+
/** The result type of a call to a built-in function whose result type does not depend on its arguments,
|
|
95829
|
+
* undefined for anything else, e.g. abs( ) or xsdbool( ), or a method of the same name */
|
|
95830
|
+
builtinResultType(chain, scope) {
|
|
95831
|
+
var _a;
|
|
95832
|
+
const children = chain.getChildren();
|
|
95833
|
+
if (children.length !== 1 || !(children[0].get() instanceof Expressions.MethodCall)) {
|
|
95834
|
+
return undefined;
|
|
95835
|
+
}
|
|
95836
|
+
const name = (_a = children[0].findDirectExpression(Expressions.MethodName)) === null || _a === void 0 ? void 0 : _a.getFirstToken();
|
|
95837
|
+
if (name === undefined) {
|
|
95838
|
+
return undefined;
|
|
95839
|
+
}
|
|
95840
|
+
const isBuiltin = scope.getData().references.some(reference => reference.referenceType === _reference_1.ReferenceType.BuiltinMethodReference
|
|
95841
|
+
&& reference.position.getStart().equals(name.getStart()));
|
|
95842
|
+
if (isBuiltin === false) {
|
|
95843
|
+
return undefined;
|
|
95844
|
+
}
|
|
95845
|
+
const upper = name.getStr().toUpperCase();
|
|
95846
|
+
if (RedundantConversion.stringResult.has(upper)) {
|
|
95847
|
+
return basic_1.StringType.get();
|
|
95848
|
+
}
|
|
95849
|
+
else if (RedundantConversion.integerResult.has(upper)) {
|
|
95850
|
+
return basic_1.IntegerType.get();
|
|
95851
|
+
}
|
|
95852
|
+
return undefined;
|
|
95853
|
+
}
|
|
95605
95854
|
fieldChainType(fieldChain, scope) {
|
|
95606
95855
|
var _a;
|
|
95607
95856
|
const operand = (_a = scope.getData().references.find(reference => reference.referenceType === _reference_1.ReferenceType.DataReadReference
|
|
@@ -95666,6 +95915,17 @@ text = text.`,
|
|
|
95666
95915
|
}
|
|
95667
95916
|
}
|
|
95668
95917
|
exports.RedundantConversion = RedundantConversion;
|
|
95918
|
+
// built-in functions that always return a string, whatever their arguments
|
|
95919
|
+
RedundantConversion.stringResult = new Set([
|
|
95920
|
+
"BOOLC", "CONCAT_LINES_OF", "CONDENSE", "ESCAPE", "FROM_MIXED", "INSERT", "REPEAT", "REPLACE",
|
|
95921
|
+
"REVERSE", "SEGMENT", "SHIFT_LEFT", "SHIFT_RIGHT", "SUBSTRING", "SUBSTRING_AFTER", "SUBSTRING_BEFORE",
|
|
95922
|
+
"SUBSTRING_FROM", "SUBSTRING_TO", "TO_LOWER", "TO_MIXED", "TO_UPPER", "TRANSLATE"
|
|
95923
|
+
]);
|
|
95924
|
+
// built-in functions that always return an i
|
|
95925
|
+
RedundantConversion.integerResult = new Set([
|
|
95926
|
+
"CHARLEN", "COUNT", "COUNT_ANY_NOT_OF", "COUNT_ANY_OF", "DBMAXLEN", "DISTANCE", "FIND", "FIND_ANY_NOT_OF",
|
|
95927
|
+
"FIND_ANY_OF", "FIND_END", "LINES", "NUMOFCHAR", "STRLEN", "XSTRLEN"
|
|
95928
|
+
]);
|
|
95669
95929
|
//# sourceMappingURL=redundant_conversion.js.map
|
|
95670
95930
|
|
|
95671
95931
|
/***/ },
|
|
@@ -102871,7 +103131,7 @@ class XMLConsistency {
|
|
|
102871
103131
|
}
|
|
102872
103132
|
runTable(obj, file) {
|
|
102873
103133
|
var _a, _b, _c, _d;
|
|
102874
|
-
var _e;
|
|
103134
|
+
var _e, _f;
|
|
102875
103135
|
const issues = [];
|
|
102876
103136
|
for (const field of (_e = obj.getFields()) !== null && _e !== void 0 ? _e : []) {
|
|
102877
103137
|
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 +103140,14 @@ class XMLConsistency {
|
|
|
102880
103140
|
}
|
|
102881
103141
|
}
|
|
102882
103142
|
if (obj.getTableCategory() === Objects.TableCategory.Transparent) {
|
|
103143
|
+
// Confirmed reserved database field names, see issue #4331, DAY and HOUR reported by activation.
|
|
103144
|
+
// TRESE also contains names such as TEXT and LENGTH which are allowed here.
|
|
103145
|
+
const reservedFieldNames = ["ZONE", "HANDLER", "SECTION", "PARAMETER", "DAY", "HOUR"];
|
|
103146
|
+
for (const field of (_f = obj.getFields()) !== null && _f !== void 0 ? _f : []) {
|
|
103147
|
+
if (reservedFieldNames.includes(field.FIELDNAME.toUpperCase())) {
|
|
103148
|
+
issues.push(issue_1.Issue.atRow(file, 1, `Table field name "${field.FIELDNAME}" is reserved`, this.getMetadata().key, this.conf.severity));
|
|
103149
|
+
}
|
|
103150
|
+
}
|
|
102883
103151
|
if (!((_c = obj.getDeliveryClass()) === null || _c === void 0 ? void 0 : _c.trim())) {
|
|
102884
103152
|
const message = `Transparent table must have delivery class(CONTFLAG in DD02V) set`;
|
|
102885
103153
|
issues.push(issue_1.Issue.atRow(file, 1, message, this.getMetadata().key, this.conf.transparentTableSeverity));
|
|
@@ -104490,6 +104758,12 @@ class Chunk {
|
|
|
104490
104758
|
original: m.original,
|
|
104491
104759
|
generated: { line: m.generated.line + offset, column: m.generated.column },
|
|
104492
104760
|
}));
|
|
104761
|
+
for (const source of new Set(this.mappings.map(m => m.source))) {
|
|
104762
|
+
const contents = options?.sourceContents?.[source];
|
|
104763
|
+
if (contents !== undefined) {
|
|
104764
|
+
sourceMapGenerator.setSourceContent(sourcePaths[source] ?? source, contents);
|
|
104765
|
+
}
|
|
104766
|
+
}
|
|
104493
104767
|
const json = sourceMapGenerator.toJSON();
|
|
104494
104768
|
json.file = generatedFilename;
|
|
104495
104769
|
json.sourceRoot = "";
|
|
@@ -104501,6 +104775,231 @@ exports.Chunk = Chunk;
|
|
|
104501
104775
|
|
|
104502
104776
|
/***/ },
|
|
104503
104777
|
|
|
104778
|
+
/***/ "./node_modules/@abaplint/transpiler/build/src/db/cds_database_view.js"
|
|
104779
|
+
/*!*****************************************************************************!*\
|
|
104780
|
+
!*** ./node_modules/@abaplint/transpiler/build/src/db/cds_database_view.js ***!
|
|
104781
|
+
\*****************************************************************************/
|
|
104782
|
+
(__unused_webpack_module, exports, __webpack_require__) {
|
|
104783
|
+
|
|
104784
|
+
"use strict";
|
|
104785
|
+
|
|
104786
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
104787
|
+
if (k2 === undefined) k2 = k;
|
|
104788
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
104789
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
104790
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
104791
|
+
}
|
|
104792
|
+
Object.defineProperty(o, k2, desc);
|
|
104793
|
+
}) : (function(o, m, k, k2) {
|
|
104794
|
+
if (k2 === undefined) k2 = k;
|
|
104795
|
+
o[k2] = m[k];
|
|
104796
|
+
}));
|
|
104797
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
104798
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
104799
|
+
}) : function(o, v) {
|
|
104800
|
+
o["default"] = v;
|
|
104801
|
+
});
|
|
104802
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
104803
|
+
var ownKeys = function(o) {
|
|
104804
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
104805
|
+
var ar = [];
|
|
104806
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
104807
|
+
return ar;
|
|
104808
|
+
};
|
|
104809
|
+
return ownKeys(o);
|
|
104810
|
+
};
|
|
104811
|
+
return function (mod) {
|
|
104812
|
+
if (mod && mod.__esModule) return mod;
|
|
104813
|
+
var result = {};
|
|
104814
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
104815
|
+
__setModuleDefault(result, mod);
|
|
104816
|
+
return result;
|
|
104817
|
+
};
|
|
104818
|
+
})();
|
|
104819
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
104820
|
+
exports.CDSDatabaseView = void 0;
|
|
104821
|
+
const abaplint = __importStar(__webpack_require__(/*! @abaplint/core */ "./node_modules/@abaplint/core/build/src/index.js"));
|
|
104822
|
+
const cds = abaplint.ExpressionsCDS;
|
|
104823
|
+
/** SQL for the supported relational subset of CDS. Never discard unknown syntax. */
|
|
104824
|
+
class CDSDatabaseView {
|
|
104825
|
+
reg;
|
|
104826
|
+
viewName = "";
|
|
104827
|
+
sources = [];
|
|
104828
|
+
constructor(reg) {
|
|
104829
|
+
this.reg = reg;
|
|
104830
|
+
}
|
|
104831
|
+
build(obj) {
|
|
104832
|
+
this.viewName = obj.getName();
|
|
104833
|
+
const tree = new abaplint.CDSParser().parse(obj.findSourceFile());
|
|
104834
|
+
if (tree === undefined) {
|
|
104835
|
+
return this.unsupported("could not parse CDS definition");
|
|
104836
|
+
}
|
|
104837
|
+
else if (!(tree.get() instanceof cds.CDSDefineView)) {
|
|
104838
|
+
return undefined; // Abstract/custom entities have no database view.
|
|
104839
|
+
}
|
|
104840
|
+
const name = tree.findDirectExpression(cds.CDSName);
|
|
104841
|
+
const select = tree.findDirectExpression(cds.CDSSelect);
|
|
104842
|
+
if (name === undefined || select === undefined) {
|
|
104843
|
+
return this.unsupported("expected a SELECT view");
|
|
104844
|
+
}
|
|
104845
|
+
this.viewName = this.name(name);
|
|
104846
|
+
for (const child of tree.getChildren()) {
|
|
104847
|
+
if (child === name || child === select || child.get() instanceof cds.CDSAnnotation) {
|
|
104848
|
+
continue;
|
|
104849
|
+
}
|
|
104850
|
+
this.keyword(child, ["DEFINE", "ROOT", "VIEW", "ENTITY", "AS", ";"]);
|
|
104851
|
+
}
|
|
104852
|
+
const source = select.findDirectExpression(cds.CDSSource);
|
|
104853
|
+
if (source === undefined) {
|
|
104854
|
+
return this.unsupported("missing source");
|
|
104855
|
+
}
|
|
104856
|
+
const from = [this.source(source)];
|
|
104857
|
+
for (const join of select.findDirectExpressions(cds.CDSJoin)) {
|
|
104858
|
+
from.push(this.join(join));
|
|
104859
|
+
}
|
|
104860
|
+
const elements = select.findDirectExpressions(cds.CDSElement);
|
|
104861
|
+
if (elements.length === 0) {
|
|
104862
|
+
return this.unsupported("expected explicit projected fields");
|
|
104863
|
+
}
|
|
104864
|
+
const columns = elements.map(e => this.element(e)).join(", ");
|
|
104865
|
+
let where = "";
|
|
104866
|
+
for (const child of select.getChildren()) {
|
|
104867
|
+
if (child === source || child.get() instanceof cds.CDSJoin || child.get() instanceof cds.CDSElement) {
|
|
104868
|
+
continue;
|
|
104869
|
+
}
|
|
104870
|
+
else if (child.get() instanceof cds.CDSWhere) {
|
|
104871
|
+
where = " " + this.expression(child);
|
|
104872
|
+
}
|
|
104873
|
+
else {
|
|
104874
|
+
this.keyword(child, ["SELECT", "DISTINCT", "FROM", "{", "}", ","]);
|
|
104875
|
+
}
|
|
104876
|
+
}
|
|
104877
|
+
const distinct = select.findDirectTokenByText("DISTINCT") ? "DISTINCT " : "";
|
|
104878
|
+
return `CREATE VIEW ${this.quote(this.viewName)} AS SELECT ${distinct}${columns} FROM ${from.join(" ")}${where};`;
|
|
104879
|
+
}
|
|
104880
|
+
source(node) {
|
|
104881
|
+
const nameNode = node.findDirectExpression(cds.CDSPrefixedName);
|
|
104882
|
+
if (nameNode === undefined) {
|
|
104883
|
+
return this.unsupported("expected a table source");
|
|
104884
|
+
}
|
|
104885
|
+
const name = this.name(nameNode);
|
|
104886
|
+
if (this.reg.getObject("TABL", name)?.getType() !== "TABL") {
|
|
104887
|
+
return this.unsupported(`source ${name} does not resolve to a TABL`);
|
|
104888
|
+
}
|
|
104889
|
+
const as = node.findDirectExpression(cds.CDSAs);
|
|
104890
|
+
const alias = as?.findDirectExpression(cds.CDSName) || node.findDirectExpression(cds.CDSName);
|
|
104891
|
+
for (const child of node.getChildren()) {
|
|
104892
|
+
if (child !== nameNode && child !== as && child !== alias) {
|
|
104893
|
+
return this.unsupported("source parameters, filters or nested joins");
|
|
104894
|
+
}
|
|
104895
|
+
}
|
|
104896
|
+
this.sources.push(alias ? this.name(alias) : name);
|
|
104897
|
+
return this.quote(name) + (alias ? " AS " + this.quote(this.name(alias)) : "");
|
|
104898
|
+
}
|
|
104899
|
+
join(node) {
|
|
104900
|
+
const sources = node.findDirectExpressions(cds.CDSSource);
|
|
104901
|
+
const conditions = node.findDirectExpressions(cds.CDSCondition);
|
|
104902
|
+
const words = node.getDirectTokens().map(t => t.getStr().toUpperCase()).join(" ");
|
|
104903
|
+
const match = /^(?:(INNER|LEFT OUTER|RIGHT OUTER|CROSS) )?JOIN(?: ON)?$/.exec(words);
|
|
104904
|
+
if (sources.length !== 1 || match === null) {
|
|
104905
|
+
return this.unsupported("join shape: " + node.concatTokens());
|
|
104906
|
+
}
|
|
104907
|
+
const kind = match[1] || "INNER";
|
|
104908
|
+
if (conditions.length !== (kind === "CROSS" ? 0 : 1)) {
|
|
104909
|
+
return this.unsupported("join requires an ON condition (except CROSS JOIN)");
|
|
104910
|
+
}
|
|
104911
|
+
const source = this.source(sources[0]);
|
|
104912
|
+
return kind + " JOIN " + source + (conditions.length ? " ON " + this.expression(conditions[0]) : "");
|
|
104913
|
+
}
|
|
104914
|
+
element(node) {
|
|
104915
|
+
const field = node.findDirectExpression(cds.CDSPrefixedName);
|
|
104916
|
+
const as = node.findDirectExpression(cds.CDSAs);
|
|
104917
|
+
for (const child of node.getChildren()) {
|
|
104918
|
+
if (child === field || child === as || child.get() instanceof cds.CDSAnnotation) {
|
|
104919
|
+
continue;
|
|
104920
|
+
}
|
|
104921
|
+
this.keyword(child, ["KEY"]);
|
|
104922
|
+
}
|
|
104923
|
+
if (field === undefined) {
|
|
104924
|
+
return this.unsupported("expected a projected source field");
|
|
104925
|
+
}
|
|
104926
|
+
const parts = this.fieldParts(field);
|
|
104927
|
+
const alias = as?.findDirectExpression(cds.CDSName);
|
|
104928
|
+
return this.field(field) + " AS " + this.quote(alias ? this.name(alias) : parts[parts.length - 1]);
|
|
104929
|
+
}
|
|
104930
|
+
expression(node) {
|
|
104931
|
+
if (node instanceof abaplint.Nodes.TokenNode) {
|
|
104932
|
+
return this.keyword(node, ["WHERE", "AND", "OR", "NOT", "IS", "NULL", "LIKE", "ESCAPE", "BETWEEN",
|
|
104933
|
+
"=", "!", "<", ">", "(", ")"]);
|
|
104934
|
+
}
|
|
104935
|
+
else if (node.get() instanceof cds.CDSPrefixedName) {
|
|
104936
|
+
if (node.getTokens().map(t => t.getStr()).join("").toLowerCase() === "$session.system_language") {
|
|
104937
|
+
return "'E'";
|
|
104938
|
+
}
|
|
104939
|
+
return this.field(node);
|
|
104940
|
+
}
|
|
104941
|
+
else if (node.get() instanceof cds.CDSString || node.get() instanceof cds.CDSInteger) {
|
|
104942
|
+
return node.getTokens().map(t => t.getStr()).join("");
|
|
104943
|
+
}
|
|
104944
|
+
else if (node.get() instanceof cds.CDSCondition || node.get() instanceof cds.CDSWhere) {
|
|
104945
|
+
const parts = [];
|
|
104946
|
+
for (const child of node.getChildren()) {
|
|
104947
|
+
const part = this.expression(child);
|
|
104948
|
+
if (["<", ">", "!"].includes(parts[parts.length - 1]) && ["=", ">"].includes(part)) {
|
|
104949
|
+
parts[parts.length - 1] += part;
|
|
104950
|
+
}
|
|
104951
|
+
else {
|
|
104952
|
+
parts.push(part);
|
|
104953
|
+
}
|
|
104954
|
+
}
|
|
104955
|
+
return parts.join(" ");
|
|
104956
|
+
}
|
|
104957
|
+
return this.unsupported(node.concatTokens());
|
|
104958
|
+
}
|
|
104959
|
+
field(node) {
|
|
104960
|
+
const parts = this.fieldParts(node);
|
|
104961
|
+
if (parts.length === 1 && this.sources.length === 1) {
|
|
104962
|
+
parts.unshift(this.sources[0]);
|
|
104963
|
+
}
|
|
104964
|
+
else if (parts.length === 2 && !this.sources.includes(parts[0])) {
|
|
104965
|
+
return this.unsupported("unknown source qualifier " + parts[0]);
|
|
104966
|
+
}
|
|
104967
|
+
return parts.map(p => this.quote(p)).join(".");
|
|
104968
|
+
}
|
|
104969
|
+
fieldParts(node) {
|
|
104970
|
+
const text = node.getTokens().map(t => t.getStr()).join("").toLowerCase();
|
|
104971
|
+
const parts = text.split(".");
|
|
104972
|
+
if (parts.length > 2 || parts.some(p => !/^(\/\w+\/)?\w+$/.test(p))) {
|
|
104973
|
+
return this.unsupported("field path " + text);
|
|
104974
|
+
}
|
|
104975
|
+
return parts;
|
|
104976
|
+
}
|
|
104977
|
+
name(node) {
|
|
104978
|
+
const name = node.getTokens().map(t => t.getStr()).join("").toLowerCase();
|
|
104979
|
+
if (!/^(\/\w+\/)?\w+$/.test(name)) {
|
|
104980
|
+
return this.unsupported("identifier " + name);
|
|
104981
|
+
}
|
|
104982
|
+
return name;
|
|
104983
|
+
}
|
|
104984
|
+
keyword(node, allowed) {
|
|
104985
|
+
const text = node.concatTokens().toUpperCase();
|
|
104986
|
+
if (!(node instanceof abaplint.Nodes.TokenNode) || !allowed.includes(text)) {
|
|
104987
|
+
return this.unsupported(node.concatTokens());
|
|
104988
|
+
}
|
|
104989
|
+
return text;
|
|
104990
|
+
}
|
|
104991
|
+
quote(name) {
|
|
104992
|
+
return '"' + name.toLowerCase().replace(/"/g, '""') + '"';
|
|
104993
|
+
}
|
|
104994
|
+
unsupported(detail) {
|
|
104995
|
+
throw new Error(`CDS view ${this.viewName}: unsupported database definition: ${detail}`);
|
|
104996
|
+
}
|
|
104997
|
+
}
|
|
104998
|
+
exports.CDSDatabaseView = CDSDatabaseView;
|
|
104999
|
+
//# sourceMappingURL=cds_database_view.js.map
|
|
105000
|
+
|
|
105001
|
+
/***/ },
|
|
105002
|
+
|
|
104504
105003
|
/***/ "./node_modules/@abaplint/transpiler/build/src/db/index.js"
|
|
104505
105004
|
/*!*****************************************************************!*\
|
|
104506
105005
|
!*** ./node_modules/@abaplint/transpiler/build/src/db/index.js ***!
|
|
@@ -104549,6 +105048,7 @@ const sqlite_database_schema_1 = __webpack_require__(/*! ./schema_generation/sql
|
|
|
104549
105048
|
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
105049
|
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
105050
|
const populate_tables_1 = __webpack_require__(/*! ./populate_tables */ "./node_modules/@abaplint/transpiler/build/src/db/populate_tables.js");
|
|
105051
|
+
const cds_database_view_1 = __webpack_require__(/*! ./cds_database_view */ "./node_modules/@abaplint/transpiler/build/src/db/cds_database_view.js");
|
|
104552
105052
|
/////////////////////////
|
|
104553
105053
|
// NOTES
|
|
104554
105054
|
/////////////////////////
|
|
@@ -104560,9 +105060,11 @@ class DatabaseSetup {
|
|
|
104560
105060
|
this.reg = reg;
|
|
104561
105061
|
}
|
|
104562
105062
|
run(options) {
|
|
105063
|
+
// CDS views are dialect independent SQL, added after the tables and views they select from
|
|
105064
|
+
const cdsViews = this.buildCDSViews();
|
|
104563
105065
|
return {
|
|
104564
105066
|
schemas: {
|
|
104565
|
-
sqlite: this.driver(new sqlite_database_schema_1.SQLiteDatabaseSchema(this.reg)),
|
|
105067
|
+
sqlite: [...this.driver(new sqlite_database_schema_1.SQLiteDatabaseSchema(this.reg)), ...cdsViews],
|
|
104566
105068
|
// HANA takes the PG schema unchanged -- measured against HANA Express
|
|
104567
105069
|
// on a tree of 77 tables. The one thing it needs is that identifiers
|
|
104568
105070
|
// reach it quoted in UPPER case, and that is not a dialect of DDL: the
|
|
@@ -104571,13 +105073,25 @@ class DatabaseSetup {
|
|
|
104571
105073
|
// here. (Unquoted would nearly work and then meet a column called
|
|
104572
105074
|
// `cross`, which is one of HANA's reserved words.)
|
|
104573
105075
|
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)),
|
|
105076
|
+
pg: [...this.driver(new pg_database_schema_1.PGDatabaseSchema(this.reg)), ...cdsViews],
|
|
105077
|
+
snowflake: [...this.driver(new snowflake_database_schema_1.SnowflakeDatabaseSchema(this.reg)), ...cdsViews],
|
|
104576
105078
|
},
|
|
104577
105079
|
insert: this.buildInsert(options),
|
|
104578
105080
|
};
|
|
104579
105081
|
}
|
|
104580
105082
|
////////////////////
|
|
105083
|
+
buildCDSViews() {
|
|
105084
|
+
const views = [];
|
|
105085
|
+
for (const obj of this.reg.getObjects()) {
|
|
105086
|
+
if (obj instanceof abaplint.Objects.DataDefinition) {
|
|
105087
|
+
const view = new cds_database_view_1.CDSDatabaseView(this.reg).build(obj);
|
|
105088
|
+
if (view !== undefined) {
|
|
105089
|
+
views.push(view);
|
|
105090
|
+
}
|
|
105091
|
+
}
|
|
105092
|
+
}
|
|
105093
|
+
return views;
|
|
105094
|
+
}
|
|
104581
105095
|
driver(schemaGenerator) {
|
|
104582
105096
|
const statements = [];
|
|
104583
105097
|
// CREATE TABLEs
|
|
@@ -105728,12 +106242,12 @@ class CompareTranspiler {
|
|
|
105728
106242
|
const field = concat.replace(" IS NOT REQUESTED", "").toLowerCase();
|
|
105729
106243
|
return new chunk_1.Chunk().appendString(pre + "INPUT && INPUT." + field + " === undefined && INPUT.importing?." + field + " === undefined");
|
|
105730
106244
|
}
|
|
105731
|
-
if (concat.includes(" IS INSTANCE OF ")) {
|
|
105732
|
-
const notted = concat.startsWith("NOT ")
|
|
106245
|
+
if (concat.includes(" IS INSTANCE OF ") || concat.includes(" IS NOT INSTANCE OF ")) {
|
|
106246
|
+
const notted = concat.startsWith("NOT ") !== concat.includes(" IS NOT INSTANCE OF ");
|
|
105733
106247
|
const falsed = notted ? " === false" : "";
|
|
105734
106248
|
const expr = node.findDirectExpression(core_1.Expressions.ClassName);
|
|
105735
106249
|
const cname = expr?.concatTokens();
|
|
105736
|
-
const lookup = traversal.lookupClassOrInterface(cname, expr?.getFirstToken());
|
|
106250
|
+
const lookup = cname?.toUpperCase() === "OBJECT" ? '"OBJECT"' : traversal.lookupClassOrInterface(cname, expr?.getFirstToken());
|
|
105737
106251
|
return new chunk_1.Chunk().appendString("abap.compare.instance_of(").appendChunk(s0).appendString(`, ${lookup})` + falsed);
|
|
105738
106252
|
}
|
|
105739
106253
|
}
|
|
@@ -111383,10 +111897,12 @@ const traversal_1 = __webpack_require__(/*! ../traversal */ "./node_modules/@aba
|
|
|
111383
111897
|
const requires_1 = __webpack_require__(/*! ../requires */ "./node_modules/@abaplint/transpiler/build/src/requires.js");
|
|
111384
111898
|
const rearranger_1 = __webpack_require__(/*! ../rearranger */ "./node_modules/@abaplint/transpiler/build/src/rearranger.js");
|
|
111385
111899
|
const chunk_1 = __webpack_require__(/*! ../chunk */ "./node_modules/@abaplint/transpiler/build/src/chunk.js");
|
|
111386
|
-
const
|
|
111900
|
+
const output_layout_1 = __webpack_require__(/*! ../output_layout */ "./node_modules/@abaplint/transpiler/build/src/output_layout.js");
|
|
111387
111901
|
class HandleABAP {
|
|
111902
|
+
layout;
|
|
111388
111903
|
options;
|
|
111389
|
-
constructor(options) {
|
|
111904
|
+
constructor(options, layout = new output_layout_1.OutputLayout()) {
|
|
111905
|
+
this.layout = layout;
|
|
111390
111906
|
this.options = options;
|
|
111391
111907
|
}
|
|
111392
111908
|
runObject(obj, reg) {
|
|
@@ -111487,11 +112003,12 @@ class HandleABAP {
|
|
|
111487
112003
|
if (filename === output.filename) {
|
|
111488
112004
|
continue;
|
|
111489
112005
|
}
|
|
112006
|
+
const specifier = (0, output_layout_1.importPath)(this.layout.file(output.object, output.filename), this.layout.sourceModule(r.filename));
|
|
111490
112007
|
if (name) {
|
|
111491
|
-
contents.appendString("const {" + traversal_1.Traversal.escapeNamespace(name) + "} = await import(\"
|
|
112008
|
+
contents.appendString("const {" + traversal_1.Traversal.escapeNamespace(name) + "} = await import(\"" + specifier + "\");\n");
|
|
111492
112009
|
}
|
|
111493
112010
|
else {
|
|
111494
|
-
contents.appendString("await import(\"
|
|
112011
|
+
contents.appendString("await import(\"" + specifier + "\");\n");
|
|
111495
112012
|
}
|
|
111496
112013
|
}
|
|
111497
112014
|
contents.appendChunk(output.chunk);
|
|
@@ -111819,7 +112336,13 @@ exports.HandleOA2P = HandleOA2P;
|
|
|
111819
112336
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
111820
112337
|
exports.HandleSMIM = void 0;
|
|
111821
112338
|
const chunk_1 = __webpack_require__(/*! ../chunk */ "./node_modules/@abaplint/transpiler/build/src/chunk.js");
|
|
112339
|
+
const output_layout_1 = __webpack_require__(/*! ../output_layout */ "./node_modules/@abaplint/transpiler/build/src/output_layout.js");
|
|
111822
112340
|
class HandleSMIM {
|
|
112341
|
+
layout;
|
|
112342
|
+
constructor(layout = new output_layout_1.OutputLayout()) {
|
|
112343
|
+
this.layout = layout;
|
|
112344
|
+
// Asset paths are relative to the output root.
|
|
112345
|
+
}
|
|
111823
112346
|
runObject(obj, _reg) {
|
|
111824
112347
|
const filename = obj.getXMLFile()?.getFilename().replace(".xml", ".mjs").toLowerCase();
|
|
111825
112348
|
if (filename === undefined) {
|
|
@@ -111827,9 +112350,10 @@ class HandleSMIM {
|
|
|
111827
112350
|
}
|
|
111828
112351
|
obj.parse();
|
|
111829
112352
|
const dataFile = obj.getDataFile();
|
|
112353
|
+
const dataFilename = dataFile ? this.layout.file({ name: obj.getName(), type: obj.getType() }, dataFile.getFilename()) : undefined;
|
|
111830
112354
|
const chunk = new chunk_1.Chunk().appendString(`abap.SMIM["${obj.getName().toUpperCase()}"] = {
|
|
111831
112355
|
"objectType": "SMIM",
|
|
111832
|
-
"filename": ${JSON.stringify(
|
|
112356
|
+
"filename": ${JSON.stringify(dataFilename)},
|
|
111833
112357
|
"url": ${JSON.stringify(obj.getURL())},
|
|
111834
112358
|
"class": ${JSON.stringify(obj.getClass())},
|
|
111835
112359
|
};`);
|
|
@@ -112102,8 +112626,14 @@ exports.HandleView = HandleView;
|
|
|
112102
112626
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
112103
112627
|
exports.HandleW3MI = void 0;
|
|
112104
112628
|
const chunk_1 = __webpack_require__(/*! ../chunk */ "./node_modules/@abaplint/transpiler/build/src/chunk.js");
|
|
112629
|
+
const output_layout_1 = __webpack_require__(/*! ../output_layout */ "./node_modules/@abaplint/transpiler/build/src/output_layout.js");
|
|
112105
112630
|
const w3mi_name_1 = __webpack_require__(/*! ../w3mi_name */ "./node_modules/@abaplint/transpiler/build/src/w3mi_name.js");
|
|
112106
112631
|
class HandleW3MI {
|
|
112632
|
+
layout;
|
|
112633
|
+
constructor(layout = new output_layout_1.OutputLayout()) {
|
|
112634
|
+
this.layout = layout;
|
|
112635
|
+
// Asset paths are relative to the output root.
|
|
112636
|
+
}
|
|
112107
112637
|
runObject(obj, _reg) {
|
|
112108
112638
|
const filename = obj.getXMLFile()?.getFilename().replace(".xml", ".mjs").toLowerCase();
|
|
112109
112639
|
if (filename === undefined) {
|
|
@@ -112111,9 +112641,10 @@ class HandleW3MI {
|
|
|
112111
112641
|
}
|
|
112112
112642
|
obj.parse();
|
|
112113
112643
|
const dataFile = obj.getDataFile();
|
|
112644
|
+
const dataFilename = dataFile ? this.layout.file({ name: obj.getName(), type: obj.getType() }, dataFile.getFilename()) : undefined;
|
|
112114
112645
|
const chunk = new chunk_1.Chunk().appendString(`abap.W3MI["${(0, w3mi_name_1.w3miObjectName)(obj)}"] = {
|
|
112115
112646
|
"objectType": "W3MI",
|
|
112116
|
-
"filename": ${JSON.stringify(
|
|
112647
|
+
"filename": ${JSON.stringify(dataFilename)},
|
|
112117
112648
|
};`);
|
|
112118
112649
|
const output = {
|
|
112119
112650
|
object: {
|
|
@@ -112189,7 +112720,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
112189
112720
|
};
|
|
112190
112721
|
})();
|
|
112191
112722
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
112192
|
-
exports.Transpiler = exports.Chunk = exports.UnknownTypesEnum = exports.config = void 0;
|
|
112723
|
+
exports.Transpiler = exports.Chunk = exports.UnknownTypesEnum = exports.config = exports.importPath = exports.OutputLayout = void 0;
|
|
112193
112724
|
const abaplint = __importStar(__webpack_require__(/*! @abaplint/core */ "./node_modules/@abaplint/core/build/src/index.js"));
|
|
112194
112725
|
const validation_1 = __webpack_require__(/*! ./validation */ "./node_modules/@abaplint/transpiler/build/src/validation.js");
|
|
112195
112726
|
Object.defineProperty(exports, "config", ({ enumerable: true, get: function () { return validation_1.config; } }));
|
|
@@ -112213,12 +112744,14 @@ const handle_msag_1 = __webpack_require__(/*! ./handlers/handle_msag */ "./node_
|
|
|
112213
112744
|
const handle_oa2p_1 = __webpack_require__(/*! ./handlers/handle_oa2p */ "./node_modules/@abaplint/transpiler/build/src/handlers/handle_oa2p.js");
|
|
112214
112745
|
const handle_fugr_1 = __webpack_require__(/*! ./handlers/handle_fugr */ "./node_modules/@abaplint/transpiler/build/src/handlers/handle_fugr.js");
|
|
112215
112746
|
const initialization_1 = __webpack_require__(/*! ./initialization */ "./node_modules/@abaplint/transpiler/build/src/initialization.js");
|
|
112747
|
+
const output_layout_1 = __webpack_require__(/*! ./output_layout */ "./node_modules/@abaplint/transpiler/build/src/output_layout.js");
|
|
112748
|
+
var output_layout_2 = __webpack_require__(/*! ./output_layout */ "./node_modules/@abaplint/transpiler/build/src/output_layout.js");
|
|
112749
|
+
Object.defineProperty(exports, "OutputLayout", ({ enumerable: true, get: function () { return output_layout_2.OutputLayout; } }));
|
|
112750
|
+
Object.defineProperty(exports, "importPath", ({ enumerable: true, get: function () { return output_layout_2.importPath; } }));
|
|
112216
112751
|
class Transpiler {
|
|
112217
112752
|
options;
|
|
112218
|
-
|
|
112219
|
-
constructor(options, plugin) {
|
|
112753
|
+
constructor(options) {
|
|
112220
112754
|
this.options = options;
|
|
112221
|
-
this.plugin = plugin;
|
|
112222
112755
|
if (this.options === undefined) {
|
|
112223
112756
|
this.options = {};
|
|
112224
112757
|
}
|
|
@@ -112232,23 +112765,22 @@ class Transpiler {
|
|
|
112232
112765
|
const reg = new abaplint.Registry().addFiles(memory);
|
|
112233
112766
|
return this.run(reg);
|
|
112234
112767
|
}
|
|
112235
|
-
async run(reg, progress) {
|
|
112768
|
+
async run(reg, progress, folders) {
|
|
112236
112769
|
// Validation installs the transpiler configuration and findIssues() parses
|
|
112237
112770
|
// dirty registries. Parsing before that would be wasted because setConfig()
|
|
112238
112771
|
// marks every registry object dirty again.
|
|
112239
112772
|
this.validate(reg);
|
|
112773
|
+
const layout = new output_layout_1.OutputLayout(reg, folders);
|
|
112240
112774
|
const dbSetup = new db_1.DatabaseSetup(reg).run(this.options);
|
|
112241
|
-
this.plugin?.amendDatabaseSetup?.(dbSetup, reg, this.options || {});
|
|
112242
112775
|
const output = {
|
|
112243
112776
|
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),
|
|
112777
|
+
unitTestScript: new unit_test_1.UnitTest(layout).unitTestScript(reg, this.options?.skip),
|
|
112778
|
+
unitTestScriptOpen: new unit_test_1.UnitTest(layout).unitTestScriptOpen(reg, this.options?.skip),
|
|
112246
112779
|
initializationScript: "",
|
|
112247
112780
|
initializationScript2: "",
|
|
112248
112781
|
databaseSetup: dbSetup,
|
|
112249
112782
|
reg: reg,
|
|
112250
112783
|
};
|
|
112251
|
-
const pluginOutputs = [];
|
|
112252
112784
|
progress?.set(reg.getObjectCount().total, "Building");
|
|
112253
112785
|
for (const obj of reg.getObjects()) {
|
|
112254
112786
|
await progress?.tick("Building, " + obj.getName());
|
|
@@ -112265,7 +112797,7 @@ class Transpiler {
|
|
|
112265
112797
|
output.objects.push(...new handle_fugr_1.HandleFUGR(this.options).runObject(obj, reg));
|
|
112266
112798
|
}
|
|
112267
112799
|
else if (obj instanceof abaplint.ABAPObject) {
|
|
112268
|
-
output.objects.push(...new handle_abap_1.HandleABAP(this.options).runObject(obj, reg));
|
|
112800
|
+
output.objects.push(...new handle_abap_1.HandleABAP(this.options, layout).runObject(obj, reg));
|
|
112269
112801
|
}
|
|
112270
112802
|
else if (obj instanceof abaplint.Objects.Oauth2Profile) {
|
|
112271
112803
|
output.objects.push(...new handle_oa2p_1.HandleOA2P().runObject(obj, reg));
|
|
@@ -112286,30 +112818,25 @@ class Transpiler {
|
|
|
112286
112818
|
output.objects.push(...new handle_table_type_1.HandleTableType().runObject(obj, reg));
|
|
112287
112819
|
}
|
|
112288
112820
|
else if (obj instanceof abaplint.Objects.MIMEObject) {
|
|
112289
|
-
output.objects.push(...new handle_smim_1.HandleSMIM().runObject(obj, reg));
|
|
112821
|
+
output.objects.push(...new handle_smim_1.HandleSMIM(layout).runObject(obj, reg));
|
|
112290
112822
|
}
|
|
112291
112823
|
else if (obj instanceof abaplint.Objects.WebMIME) {
|
|
112292
|
-
output.objects.push(...new handle_w3mi_1.HandleW3MI().runObject(obj, reg));
|
|
112824
|
+
output.objects.push(...new handle_w3mi_1.HandleW3MI(layout).runObject(obj, reg));
|
|
112293
112825
|
}
|
|
112294
112826
|
else if (obj instanceof abaplint.Objects.MessageClass) {
|
|
112295
112827
|
output.objects.push(...new handle_msag_1.HandleMSAG().runObject(obj, reg));
|
|
112296
112828
|
}
|
|
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
112829
|
}
|
|
112305
|
-
|
|
112306
|
-
output.
|
|
112307
|
-
|
|
112830
|
+
output.initializationScript = new initialization_1.Initialization(layout).script(reg, dbSetup, this.options, false);
|
|
112831
|
+
output.initializationScript2 = new initialization_1.Initialization(layout).script(reg, dbSetup, this.options, true);
|
|
112832
|
+
for (const file of output.objects) {
|
|
112833
|
+
file.filename = layout.file(file.object, file.filename);
|
|
112834
|
+
}
|
|
112308
112835
|
return output;
|
|
112309
112836
|
}
|
|
112310
112837
|
// ///////////////////////////////
|
|
112311
112838
|
validate(reg) {
|
|
112312
|
-
const issues = new validation_1.Validation(this.options
|
|
112839
|
+
const issues = new validation_1.Validation(this.options).run(reg);
|
|
112313
112840
|
if (issues.length > 0) {
|
|
112314
112841
|
const messages = issues.map(i => i.getKey() + ", " +
|
|
112315
112842
|
i.getMessage() + ", " +
|
|
@@ -112371,6 +112898,7 @@ exports.escapeNamespaceFilename = escapeNamespaceFilename;
|
|
|
112371
112898
|
exports.escapeFilenameForImport = escapeFilenameForImport;
|
|
112372
112899
|
const abaplint = __importStar(__webpack_require__(/*! @abaplint/core */ "./node_modules/@abaplint/core/build/src/index.js"));
|
|
112373
112900
|
const handle_fugr_1 = __webpack_require__(/*! ./handlers/handle_fugr */ "./node_modules/@abaplint/transpiler/build/src/handlers/handle_fugr.js");
|
|
112901
|
+
const output_layout_1 = __webpack_require__(/*! ./output_layout */ "./node_modules/@abaplint/transpiler/build/src/output_layout.js");
|
|
112374
112902
|
function escapeNamespaceFilename(filename) {
|
|
112375
112903
|
// ES modules are resolved and cached as URLs. This means that special characters must be
|
|
112376
112904
|
// percent-encoded, such as # with %23 and ? with %3F.
|
|
@@ -112388,7 +112916,12 @@ function escapeFilenameForImport(filename) {
|
|
|
112388
112916
|
return filename.replace(/%/g, "%25").replace(/#/g, "%23");
|
|
112389
112917
|
}
|
|
112390
112918
|
class Initialization {
|
|
112391
|
-
|
|
112919
|
+
layout;
|
|
112920
|
+
constructor(layout = new output_layout_1.OutputLayout()) {
|
|
112921
|
+
this.layout = layout;
|
|
112922
|
+
// Flat output unless the caller supplies ownership information.
|
|
112923
|
+
}
|
|
112924
|
+
script(reg, dbSetup, options, useImport) {
|
|
112392
112925
|
let ret = "";
|
|
112393
112926
|
if (useImport === true) {
|
|
112394
112927
|
ret = `/* eslint-disable import/newline-after-import */
|
|
@@ -112431,28 +112964,24 @@ globalThis.abap = new runtime.ABAP();\n`;
|
|
|
112431
112964
|
}
|
|
112432
112965
|
ret += `}\n\n`;
|
|
112433
112966
|
ret += `await initializeABAP();\n\n`;
|
|
112434
|
-
ret += `${this.buildImports(reg, useImport, options
|
|
112967
|
+
ret += `${this.buildImports(reg, useImport, options)}`;
|
|
112435
112968
|
if (options?.setup?.postFunction !== undefined) {
|
|
112436
112969
|
ret += `\n\nawait setup.${options?.setup?.postFunction}();\n`;
|
|
112437
112970
|
}
|
|
112438
112971
|
return ret;
|
|
112439
112972
|
}
|
|
112440
|
-
buildImports(reg, useImport, options
|
|
112973
|
+
buildImports(reg, useImport, options) {
|
|
112441
112974
|
// note: ES modules are hoised, so use the dynamic import(), due to setting of globalThis.abap
|
|
112442
112975
|
// some sorting required: eg. a class constructor using constant from interface
|
|
112443
112976
|
const list = [];
|
|
112444
112977
|
const late = [];
|
|
112445
112978
|
const imp = (filename) => {
|
|
112446
|
-
|
|
112447
|
-
|
|
112448
|
-
|
|
112449
|
-
|
|
112450
|
-
|
|
112451
|
-
}
|
|
112979
|
+
const specifier = (0, output_layout_1.importPath)("init.mjs", filename);
|
|
112980
|
+
return {
|
|
112981
|
+
filename: specifier.split("/").pop(),
|
|
112982
|
+
code: useImport === true ? `import "${specifier}";` : `await import("${specifier}");`,
|
|
112983
|
+
};
|
|
112452
112984
|
};
|
|
112453
|
-
for (const pluginOutput of pluginOutputs || []) {
|
|
112454
|
-
list.push(imp(pluginOutput.filename.replace(/\.mjs$/i, "")));
|
|
112455
|
-
}
|
|
112456
112985
|
for (const obj of reg.getObjects()) {
|
|
112457
112986
|
if (obj instanceof abaplint.Objects.Table
|
|
112458
112987
|
|| obj instanceof abaplint.Objects.DataElement
|
|
@@ -112464,11 +112993,11 @@ globalThis.abap = new runtime.ABAP();\n`;
|
|
|
112464
112993
|
|| obj instanceof abaplint.Objects.TypePool
|
|
112465
112994
|
|| obj instanceof abaplint.Objects.TableType
|
|
112466
112995
|
|| obj instanceof abaplint.Objects.View) {
|
|
112467
|
-
list.push(imp(
|
|
112996
|
+
list.push(imp(this.layout.objectModule(obj)));
|
|
112468
112997
|
}
|
|
112469
112998
|
}
|
|
112470
112999
|
for (const obj of reg.getObjects()) {
|
|
112471
|
-
const name = imp(
|
|
113000
|
+
const name = imp(this.layout.objectModule(obj));
|
|
112472
113001
|
if (obj instanceof abaplint.Objects.Class
|
|
112473
113002
|
&& obj.getName().toUpperCase() !== "CL_ABAP_CHAR_UTILITIES"
|
|
112474
113003
|
&& this.hasClassConstructor(reg, obj)) {
|
|
@@ -112488,7 +113017,9 @@ globalThis.abap = new runtime.ABAP();\n`;
|
|
|
112488
113017
|
list.push(name);
|
|
112489
113018
|
}
|
|
112490
113019
|
}
|
|
112491
|
-
|
|
113020
|
+
// Folder names must not change the original module initialization order.
|
|
113021
|
+
list.sort((a, b) => a.filename < b.filename ? -1 : a.filename > b.filename ? 1 : 0);
|
|
113022
|
+
return [...list, ...late].map(entry => entry.code).join("\n");
|
|
112492
113023
|
}
|
|
112493
113024
|
// class constructors might make early use of eg. constants from interfaces
|
|
112494
113025
|
// sub classes will import() super classes and trigger a class constructor of the super
|
|
@@ -112640,6 +113171,89 @@ exports.DEFAULT_KEYWORDS = new Set([
|
|
|
112640
113171
|
|
|
112641
113172
|
/***/ },
|
|
112642
113173
|
|
|
113174
|
+
/***/ "./node_modules/@abaplint/transpiler/build/src/output_layout.js"
|
|
113175
|
+
/*!**********************************************************************!*\
|
|
113176
|
+
!*** ./node_modules/@abaplint/transpiler/build/src/output_layout.js ***!
|
|
113177
|
+
\**********************************************************************/
|
|
113178
|
+
(__unused_webpack_module, exports) {
|
|
113179
|
+
|
|
113180
|
+
"use strict";
|
|
113181
|
+
|
|
113182
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
113183
|
+
exports.OutputLayout = void 0;
|
|
113184
|
+
exports.importPath = importPath;
|
|
113185
|
+
/** Browser-safe paths: generated modules use POSIX paths on every platform. */
|
|
113186
|
+
class OutputLayout {
|
|
113187
|
+
grouped;
|
|
113188
|
+
objectFolders = new Map();
|
|
113189
|
+
sourceFolders = new Map();
|
|
113190
|
+
constructor(reg, folders) {
|
|
113191
|
+
this.grouped = folders !== undefined;
|
|
113192
|
+
if (folders === undefined) {
|
|
113193
|
+
return;
|
|
113194
|
+
}
|
|
113195
|
+
for (const [filename, folder] of folders) {
|
|
113196
|
+
this.sourceFolders.set(filename.toLowerCase(), folder);
|
|
113197
|
+
}
|
|
113198
|
+
for (const obj of reg?.getObjects() || []) {
|
|
113199
|
+
const owners = new Set(obj.getFiles().map(f => this.sourceFolders.get(f.getFilename().toLowerCase()))
|
|
113200
|
+
.filter((folder) => folder !== undefined));
|
|
113201
|
+
if (owners.size !== 1) {
|
|
113202
|
+
throw new Error("Ambiguous output ownership for " + obj.getType() + " " + obj.getName());
|
|
113203
|
+
}
|
|
113204
|
+
const folder = [...owners][0];
|
|
113205
|
+
this.objectFolders.set(this.key({ type: obj.getType(), name: obj.getName() }), folder);
|
|
113206
|
+
for (const file of obj.getFiles()) {
|
|
113207
|
+
// Class locals are merged into a single module.
|
|
113208
|
+
this.sourceFolders.set(file.getFilename().toLowerCase().replace(/\.locals_(def|imp)\.abap$/, ".locals.abap"), folder);
|
|
113209
|
+
}
|
|
113210
|
+
}
|
|
113211
|
+
}
|
|
113212
|
+
key(obj) {
|
|
113213
|
+
return obj.type.toUpperCase() + ":" + obj.name.toUpperCase();
|
|
113214
|
+
}
|
|
113215
|
+
file(obj, filename) {
|
|
113216
|
+
const folder = this.objectFolders.get(this.key(obj));
|
|
113217
|
+
if (this.grouped && folder === undefined) {
|
|
113218
|
+
throw new Error("Missing output ownership for " + obj.type + " " + obj.name);
|
|
113219
|
+
}
|
|
113220
|
+
if (folder !== undefined && (filename.startsWith("/") || /[\\:]/.test(filename)
|
|
113221
|
+
|| filename.split("/").some(segment => segment === "" || segment === "." || segment === ".."))) {
|
|
113222
|
+
throw new Error("Invalid output filename: " + filename);
|
|
113223
|
+
}
|
|
113224
|
+
return folder === undefined ? filename : folder + "/" + filename;
|
|
113225
|
+
}
|
|
113226
|
+
sourceModule(filename) {
|
|
113227
|
+
const folder = this.sourceFolders.get(filename.toLowerCase());
|
|
113228
|
+
if (this.grouped && folder === undefined) {
|
|
113229
|
+
throw new Error("Missing output ownership for source " + filename);
|
|
113230
|
+
}
|
|
113231
|
+
const module = filename.replace(/\.abap$/i, ".mjs").toLowerCase();
|
|
113232
|
+
return folder === undefined ? module : folder + "/" + module;
|
|
113233
|
+
}
|
|
113234
|
+
objectModule(obj, suffix = "") {
|
|
113235
|
+
const identifier = { name: obj.getName(), type: obj.getType() };
|
|
113236
|
+
const filename = obj.getName().toLowerCase().replace(/\//g, "#") + "." + obj.getType().toLowerCase() + suffix + ".mjs";
|
|
113237
|
+
return this.file(identifier, filename);
|
|
113238
|
+
}
|
|
113239
|
+
}
|
|
113240
|
+
exports.OutputLayout = OutputLayout;
|
|
113241
|
+
/** Escape each segment without turning directory separators into namespace markers. */
|
|
113242
|
+
function importPath(from, to) {
|
|
113243
|
+
const source = from.split("/").slice(0, -1);
|
|
113244
|
+
const target = to.split("/");
|
|
113245
|
+
while (source.length > 0 && target.length > 0 && source[0] === target[0]) {
|
|
113246
|
+
source.shift();
|
|
113247
|
+
target.shift();
|
|
113248
|
+
}
|
|
113249
|
+
const relative = [...source.map(() => ".."), ...target].join("/");
|
|
113250
|
+
const escaped = relative.split("/").map(segment => encodeURIComponent(segment)).join("/");
|
|
113251
|
+
return escaped.startsWith("../") ? escaped : "./" + escaped;
|
|
113252
|
+
}
|
|
113253
|
+
//# sourceMappingURL=output_layout.js.map
|
|
113254
|
+
|
|
113255
|
+
/***/ },
|
|
113256
|
+
|
|
112643
113257
|
/***/ "./node_modules/@abaplint/transpiler/build/src/rearranger.js"
|
|
112644
113258
|
/*!*******************************************************************!*\
|
|
112645
113259
|
!*** ./node_modules/@abaplint/transpiler/build/src/rearranger.js ***!
|
|
@@ -113502,6 +114116,22 @@ throw error;
|
|
|
113502
114116
|
}
|
|
113503
114117
|
})())`;
|
|
113504
114118
|
}
|
|
114119
|
+
/** ASSIGN of a statically specified data object, e.g. a variable, an attribute or an offset/length,
|
|
114120
|
+
* does not set sy-subrc, a dereference, a table expression or COMPONENT does */
|
|
114121
|
+
isStaticDataObject(node, source) {
|
|
114122
|
+
const concat = node.concatTokens().toUpperCase();
|
|
114123
|
+
if (source === undefined
|
|
114124
|
+
|| concat.startsWith("ASSIGN COMPONENT ")
|
|
114125
|
+
|| concat.includes(" INCREMENT ")
|
|
114126
|
+
|| concat.includes(" ELSE UNASSIGN")
|
|
114127
|
+
|| source.findFirstExpression(abaplint.Expressions.Dereference) !== undefined
|
|
114128
|
+
|| source.findFirstExpression(abaplint.Expressions.TableExpression) !== undefined) {
|
|
114129
|
+
return false;
|
|
114130
|
+
}
|
|
114131
|
+
// field symbols are left as they are, not measured
|
|
114132
|
+
const first = source.findFirstExpression(abaplint.Expressions.FieldChain)?.getFirstChild();
|
|
114133
|
+
return first !== undefined && !(first.get() instanceof abaplint.Expressions.SourceFieldSymbol);
|
|
114134
|
+
}
|
|
113505
114135
|
transpile(node, traversal) {
|
|
113506
114136
|
const assignSource = node.findDirectExpression(abaplint.Expressions.AssignSource);
|
|
113507
114137
|
const sourceExpressions = assignSource?.findDirectExpressionsMulti([abaplint.Expressions.Source, abaplint.Expressions.SimpleSource3]) || [];
|
|
@@ -113541,6 +114171,9 @@ throw error;
|
|
|
113541
114171
|
}
|
|
113542
114172
|
else {
|
|
113543
114173
|
options.push("source: " + sources.pop());
|
|
114174
|
+
if (this.isStaticDataObject(node, sourceExprForCheck)) {
|
|
114175
|
+
options.push("keepSubrc: true");
|
|
114176
|
+
}
|
|
113544
114177
|
}
|
|
113545
114178
|
}
|
|
113546
114179
|
else {
|
|
@@ -114572,7 +115205,7 @@ static INTERNAL_TYPE = 'CLAS';
|
|
|
114572
115205
|
static INTERNAL_NAME = '${traversal.buildInternalName(token.getStr(), def)}';
|
|
114573
115206
|
static IMPLEMENTED_INTERFACES = [${this.findImplementedByClass(traversal, def, scope).map(e => `"` + e.toUpperCase() + `"`).join(",")}];
|
|
114574
115207
|
static ATTRIBUTES = {${Array.from(traversal.buildAttributes(def, scope)).join(",\n")}};
|
|
114575
|
-
static METHODS = {${traversal.buildMethods(def).join(",\n")}};`, node, traversal);
|
|
115208
|
+
static METHODS = {${traversal.buildMethods(def, scope).join(",\n")}};`, node, traversal);
|
|
114576
115209
|
}
|
|
114577
115210
|
findImplementedInterface(traversal, def, scope) {
|
|
114578
115211
|
if (def === undefined || scope === undefined) {
|
|
@@ -118964,6 +119597,16 @@ class MethodImplementationTranspiler {
|
|
|
118964
119597
|
else {
|
|
118965
119598
|
after += `let ${varPrefixed} = ${unique}?.${varName};\n`;
|
|
118966
119599
|
}
|
|
119600
|
+
if (passByValue === true) {
|
|
119601
|
+
// pass by value: the method works on its own copy, also for a generic type,
|
|
119602
|
+
// which keeps the type of the actual parameter.
|
|
119603
|
+
// A field symbol that is unassigned or assigned with CASTING is passed on as it is
|
|
119604
|
+
after += `if (${varPrefixed} instanceof abap.types.FieldSymbol) {
|
|
119605
|
+
if (${varPrefixed}.getPointer()?.clone !== undefined) { ${varPrefixed} = ${varPrefixed}.getPointer().clone(); }
|
|
119606
|
+
} else if (${unique}?.${varName} !== undefined && ${varPrefixed}?.clone !== undefined) {
|
|
119607
|
+
${varPrefixed} = ${varPrefixed}.clone();
|
|
119608
|
+
}\n`;
|
|
119609
|
+
}
|
|
118967
119610
|
if (type instanceof abaplint.BasicTypes.NumericGenericType) {
|
|
118968
119611
|
after += `if (${varPrefixed}.constructor.name === "Character") {
|
|
118969
119612
|
${varPrefixed} = ${transpile_types_1.TranspileTypes.toType(identifier.getType())};
|
|
@@ -121516,10 +122159,10 @@ abap.builtin.sy.get().dbcnt.set(${target}.getArrayLength());
|
|
|
121516
122159
|
+ ` : (("" + ${code}.get()).trim() === "" ? "" : "${keyword} " + ${code}.get()))`;
|
|
121517
122160
|
}
|
|
121518
122161
|
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 {}});
|
|
122162
|
+
return `((value) => {
|
|
122163
|
+
const condition = value instanceof abap.types.Table || value instanceof abap.types.HashedTable
|
|
122164
|
+
? value.array().map(row => row.get()).join(" ") : value.get();
|
|
122165
|
+
return condition.trim() === "" ? "" : "HAVING " + abap.expandDynamic(condition, (name) => {try { return eval(name);} catch {}});
|
|
121523
122166
|
})(${code})`;
|
|
121524
122167
|
}
|
|
121525
122168
|
isWhereExpression(node, expression) {
|
|
@@ -124762,8 +125405,11 @@ class InterfaceTranspiler {
|
|
|
124762
125405
|
ret += `static INTERNAL_TYPE = 'INTF';\n`;
|
|
124763
125406
|
ret += `static INTERNAL_NAME = '${traversal.buildInternalName(token.getStr(), def)}';\n`;
|
|
124764
125407
|
ret += `static ATTRIBUTES = {${Array.from(traversal.buildAttributes(def, scope)).join(",\n")}};\n`;
|
|
124765
|
-
ret += `static METHODS = {${traversal.buildMethods(def).join(",\n")}};\n`;
|
|
124766
|
-
|
|
125408
|
+
ret += `static METHODS = {${traversal.buildMethods(def, scope).join(",\n")}};\n`;
|
|
125409
|
+
const interfaces = def?.getImplementing().map(i => `"${i.name.toUpperCase()}"`) || [];
|
|
125410
|
+
if (interfaces.length > 0) {
|
|
125411
|
+
ret += `static IMPLEMENTED_INTERFACES = [${interfaces.join(",")}];\n`;
|
|
125412
|
+
}
|
|
124767
125413
|
}
|
|
124768
125414
|
else if (c instanceof abaplint.Nodes.StatementNode && c.get() instanceof abaplint.Statements.EndInterface) {
|
|
124769
125415
|
ret += "}\n";
|
|
@@ -125558,8 +126204,22 @@ class TranspileTypes {
|
|
|
125558
126204
|
if (type instanceof abaplint.BasicTypes.ObjectReferenceType
|
|
125559
126205
|
|| type instanceof abaplint.BasicTypes.GenericObjectReferenceType) {
|
|
125560
126206
|
resolved = "ABAPObject";
|
|
125561
|
-
|
|
125562
|
-
|
|
126207
|
+
const qualifiedName = type.getQualifiedName()
|
|
126208
|
+
?? (type instanceof abaplint.BasicTypes.ObjectReferenceType ? type.getIdentifierName() : undefined);
|
|
126209
|
+
let RTTIName = type.getRTTIName();
|
|
126210
|
+
if (type instanceof abaplint.BasicTypes.ObjectReferenceType && RTTIName === undefined) {
|
|
126211
|
+
const id = type.getIdentifier();
|
|
126212
|
+
// NEW and CAST can omit metadata; recover it from the referenced definition.
|
|
126213
|
+
const [name, kind] = id.getFilename().split("/").pop().replace(/#/g, "/").split(".");
|
|
126214
|
+
const local = (id instanceof abaplint.Types.ClassDefinition || id instanceof abaplint.Types.InterfaceDefinition)
|
|
126215
|
+
&& id.isGlobal() === false;
|
|
126216
|
+
const prefix = local && kind === "prog" ? "\\PROGRAM=" + name
|
|
126217
|
+
: local && kind === "clas" ? "\\CLASS-POOL=" + name : "";
|
|
126218
|
+
const category = id instanceof abaplint.Types.InterfaceDefinition || kind === "intf" ? "INTERFACE" : "CLASS";
|
|
126219
|
+
RTTIName = prefix + "\\" + category + "=" + id.getName();
|
|
126220
|
+
}
|
|
126221
|
+
extra = "{qualifiedName: " + JSON.stringify(qualifiedName?.toUpperCase()) +
|
|
126222
|
+
", RTTIName: " + JSON.stringify(RTTIName?.toUpperCase()) + "}";
|
|
125563
126223
|
}
|
|
125564
126224
|
else if (type instanceof abaplint.BasicTypes.TableType) {
|
|
125565
126225
|
resolved = "Table";
|
|
@@ -125687,6 +126347,11 @@ class TranspileTypes {
|
|
|
125687
126347
|
resolved = "Packed";
|
|
125688
126348
|
extra = "{length: 8, decimals: 2}";
|
|
125689
126349
|
}
|
|
126350
|
+
else if (type instanceof abaplint.BasicTypes.PGenericType) {
|
|
126351
|
+
// if not supplied its a P LENGTH 8 DECIMALS 0
|
|
126352
|
+
resolved = "Packed";
|
|
126353
|
+
extra = "{length: 8, decimals: 0}";
|
|
126354
|
+
}
|
|
125690
126355
|
else if (type instanceof abaplint.BasicTypes.XStringType) {
|
|
125691
126356
|
resolved = "XString";
|
|
125692
126357
|
if (type.getQualifiedName() !== undefined) {
|
|
@@ -126112,7 +126777,7 @@ class Traversal {
|
|
|
126112
126777
|
}
|
|
126113
126778
|
return undefined;
|
|
126114
126779
|
}
|
|
126115
|
-
buildMethods(def) {
|
|
126780
|
+
buildMethods(def, scope) {
|
|
126116
126781
|
const methods = [];
|
|
126117
126782
|
if (def === undefined) {
|
|
126118
126783
|
return methods;
|
|
@@ -126123,29 +126788,57 @@ class Traversal {
|
|
|
126123
126788
|
throw new Error("buildMethods: unexpected undefined, " + def.getName());
|
|
126124
126789
|
}
|
|
126125
126790
|
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}"}`);
|
|
126791
|
+
methods.push(this.buildMethod(m.getName(), m, m.getVisibility()));
|
|
126792
|
+
}
|
|
126793
|
+
// an alias for an interface method is listed under its own name, pointing to the method
|
|
126794
|
+
for (const a of def.getAliases() || []) {
|
|
126795
|
+
const [intfName, methodName] = a.getComponent().split("~");
|
|
126796
|
+
if (methodName === undefined) {
|
|
126797
|
+
continue;
|
|
126798
|
+
}
|
|
126799
|
+
const aliased = this.findInterfaceDefinition(intfName, scope)?.getMethodDefinitions()?.getByName(methodName);
|
|
126800
|
+
if (aliased === undefined) {
|
|
126801
|
+
// not a method, or the interface is unknown
|
|
126802
|
+
continue;
|
|
126144
126803
|
}
|
|
126145
|
-
methods.push(
|
|
126804
|
+
methods.push(this.buildMethod(a.getName(), aliased, a.getVisibility(), a.getComponent()));
|
|
126146
126805
|
}
|
|
126147
126806
|
return methods;
|
|
126148
126807
|
}
|
|
126808
|
+
buildMethod(name, m, visibility, aliasFor) {
|
|
126809
|
+
const optionalNames = m.getParameters().getOptional().map(o => o.toUpperCase());
|
|
126810
|
+
const parameters = [];
|
|
126811
|
+
for (const p of m.getParameters().getAll()) {
|
|
126812
|
+
const type = transpile_types_1.TranspileTypes.toType(p.getType());
|
|
126813
|
+
const optional = optionalNames.includes(p.getName().toUpperCase()) ? "X" : " ";
|
|
126814
|
+
let pKind = "";
|
|
126815
|
+
if (pKind === "") {
|
|
126816
|
+
pKind = m.getParameters().getImporting().find((t) => { return t.getName() === p.getName(); }) ? "I" : "";
|
|
126817
|
+
}
|
|
126818
|
+
if (pKind === "") {
|
|
126819
|
+
pKind = m.getParameters().getChanging().find((t) => { return t.getName() === p.getName(); }) ? "C" : "";
|
|
126820
|
+
}
|
|
126821
|
+
if (pKind === "") {
|
|
126822
|
+
pKind = m.getParameters().getExporting().find((t) => { return t.getName() === p.getName(); }) ? "E" : "";
|
|
126823
|
+
}
|
|
126824
|
+
if (pKind === "") {
|
|
126825
|
+
pKind = m.getParameters().getReturning()?.getName() === p.getName() ? "R" : "";
|
|
126826
|
+
}
|
|
126827
|
+
parameters.push(`"${p.getName().toUpperCase()}": {"type": () => {return ${type};}, "is_optional": "${optional}", "parm_kind": "${pKind}", "type_name": "${p.getType().constructor.name}"}`);
|
|
126828
|
+
}
|
|
126829
|
+
// only written when set, a method without them is described as before
|
|
126830
|
+
let extra = "";
|
|
126831
|
+
if (m.isStatic() === true) {
|
|
126832
|
+
extra += `"is_class": "X", `;
|
|
126833
|
+
}
|
|
126834
|
+
if (m.getRaising().length > 0) {
|
|
126835
|
+
extra += `"exceptions": [${m.getRaising().map(e => `"${e.toUpperCase()}"`).join(", ")}], `;
|
|
126836
|
+
}
|
|
126837
|
+
if (aliasFor !== undefined) {
|
|
126838
|
+
extra += `"alias_for": "${aliasFor.toUpperCase()}", `;
|
|
126839
|
+
}
|
|
126840
|
+
return `"${name.toUpperCase()}": {"visibility": "${this.mapVisibility(visibility)}", ${extra}"parameters": {${parameters.join(", ")}}}`;
|
|
126841
|
+
}
|
|
126149
126842
|
mapVisibility(vis) {
|
|
126150
126843
|
switch (vis) {
|
|
126151
126844
|
case abaplint.Visibility.Private:
|
|
@@ -127039,8 +127732,13 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
|
127039
127732
|
exports.UnitTest = void 0;
|
|
127040
127733
|
/* eslint-disable max-len */
|
|
127041
127734
|
const abaplint = __importStar(__webpack_require__(/*! @abaplint/core */ "./node_modules/@abaplint/core/build/src/index.js"));
|
|
127042
|
-
const
|
|
127735
|
+
const output_layout_1 = __webpack_require__(/*! ./output_layout */ "./node_modules/@abaplint/transpiler/build/src/output_layout.js");
|
|
127043
127736
|
class UnitTest {
|
|
127737
|
+
layout;
|
|
127738
|
+
constructor(layout = new output_layout_1.OutputLayout()) {
|
|
127739
|
+
this.layout = layout;
|
|
127740
|
+
// Test runners live at the output root.
|
|
127741
|
+
}
|
|
127044
127742
|
unitTestScriptOpen(reg, _skip) {
|
|
127045
127743
|
let ret = `/* eslint-disable curly */
|
|
127046
127744
|
import fs from "fs";
|
|
@@ -127061,7 +127759,7 @@ async function run() {
|
|
|
127061
127759
|
}
|
|
127062
127760
|
const hasTestFile = obj.getFiles().some(f => { return f.getFilename().includes(".testclasses."); });
|
|
127063
127761
|
if (hasTestFile === true) {
|
|
127064
|
-
ret += ` await import("
|
|
127762
|
+
ret += ` await import("${(0, output_layout_1.importPath)("index.mjs", this.layout.objectModule(obj, ".testclasses"))}");\n`;
|
|
127065
127763
|
}
|
|
127066
127764
|
for (const file of obj.getABAPFiles()) {
|
|
127067
127765
|
for (const def of file.getInfo().listClassDefinitions()) {
|
|
@@ -127123,7 +127821,7 @@ run().then(() => {
|
|
|
127123
127821
|
}
|
|
127124
127822
|
tests.push({
|
|
127125
127823
|
obj,
|
|
127126
|
-
filename:
|
|
127824
|
+
filename: `${(0, output_layout_1.importPath)("index.mjs", this.layout.objectModule(obj, ".testclasses"))}`,
|
|
127127
127825
|
localClass: def.name.toLowerCase(),
|
|
127128
127826
|
riskLevel: def.riskLevel,
|
|
127129
127827
|
duration: def.duration,
|
|
@@ -127268,8 +127966,12 @@ const core_1 = __webpack_require__(/*! @abaplint/core */ "./node_modules/@abapli
|
|
|
127268
127966
|
const types_1 = __webpack_require__(/*! ./types */ "./node_modules/@abaplint/transpiler/build/src/types.js");
|
|
127269
127967
|
const defaultAllowedObjectTypes = [
|
|
127270
127968
|
"APIS",
|
|
127969
|
+
"APLO",
|
|
127271
127970
|
"AUTH",
|
|
127971
|
+
"BDEF",
|
|
127272
127972
|
"CLAS",
|
|
127973
|
+
"DDLS",
|
|
127974
|
+
"DDLX",
|
|
127273
127975
|
"DEVC",
|
|
127274
127976
|
"DOMA",
|
|
127275
127977
|
"DTEL",
|
|
@@ -127291,13 +127993,19 @@ const defaultAllowedObjectTypes = [
|
|
|
127291
127993
|
"PARA",
|
|
127292
127994
|
"PINF",
|
|
127293
127995
|
"PROG",
|
|
127996
|
+
"SAJC",
|
|
127997
|
+
"SAJT",
|
|
127998
|
+
"SCO2",
|
|
127294
127999
|
"WAPA",
|
|
127295
128000
|
"SHLP",
|
|
127296
128001
|
"SHMA",
|
|
128002
|
+
"SIA6",
|
|
127297
128003
|
"SICF",
|
|
127298
128004
|
"SMIM",
|
|
127299
128005
|
"SPLO",
|
|
127300
128006
|
"SRFC",
|
|
128007
|
+
"SRVB",
|
|
128008
|
+
"SRVD",
|
|
127301
128009
|
"SUSC",
|
|
127302
128010
|
"SUSH",
|
|
127303
128011
|
"SUSO",
|
|
@@ -127373,10 +128081,8 @@ exports.config = {
|
|
|
127373
128081
|
// hmm this ^ is okay? since lines will be prefixed with "abap.builtin"?
|
|
127374
128082
|
class Validation {
|
|
127375
128083
|
options;
|
|
127376
|
-
|
|
127377
|
-
constructor(options, plugin) {
|
|
128084
|
+
constructor(options) {
|
|
127378
128085
|
this.options = options;
|
|
127379
|
-
this.plugin = plugin;
|
|
127380
128086
|
}
|
|
127381
128087
|
run(reg) {
|
|
127382
128088
|
if (this.options?.ignoreSyntaxCheck === true) {
|
|
@@ -127386,13 +128092,6 @@ class Validation {
|
|
|
127386
128092
|
exports.config.rules.check_syntax = true;
|
|
127387
128093
|
}
|
|
127388
128094
|
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
128095
|
if (this.options?.unknownTypes === types_1.UnknownTypesEnum.runtimeError) {
|
|
127397
128096
|
// this is not a constant, just a regex that happens to not match anything
|
|
127398
128097
|
exports.config.syntax.errorNamespace = "VOID_EVERYTHING";
|
|
@@ -130878,17 +131577,6 @@ module.exports = require("fs");
|
|
|
130878
131577
|
|
|
130879
131578
|
/***/ },
|
|
130880
131579
|
|
|
130881
|
-
/***/ "module"
|
|
130882
|
-
/*!*************************!*\
|
|
130883
|
-
!*** external "module" ***!
|
|
130884
|
-
\*************************/
|
|
130885
|
-
(module) {
|
|
130886
|
-
|
|
130887
|
-
"use strict";
|
|
130888
|
-
module.exports = require("module");
|
|
130889
|
-
|
|
130890
|
-
/***/ },
|
|
130891
|
-
|
|
130892
131580
|
/***/ "node:events"
|
|
130893
131581
|
/*!******************************!*\
|
|
130894
131582
|
!*** external "node:events" ***!
|