@abaplint/transpiler-cli 2.13.99 → 2.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -1
- package/build/bundle.js +1039 -243
- package/build/types.d.ts +4 -0
- package/package.json +3 -3
- package/schema.json +1 -4
- package/tsconfig.tsbuildinfo +1 -0
package/build/bundle.js
CHANGED
|
@@ -240,6 +240,7 @@ class FileOperations {
|
|
|
240
240
|
return limit(async () => {
|
|
241
241
|
// read as latin1, written as latin1: anything else re-encodes the
|
|
242
242
|
// bytes on the way out and undoes the careful read
|
|
243
|
+
await fsPromises.mkdir(path.dirname(file.path), { recursive: true });
|
|
243
244
|
await fsPromises.writeFile(file.path, file.contents, this.isBinaryFilename(file.path) ? { encoding: "latin1" } : undefined);
|
|
244
245
|
});
|
|
245
246
|
});
|
|
@@ -315,16 +316,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
315
316
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
316
317
|
const fs = __importStar(__webpack_require__(/*! fs */ "fs"));
|
|
317
318
|
const path = __importStar(__webpack_require__(/*! path */ "path"));
|
|
318
|
-
const childProcess = __importStar(__webpack_require__(/*! child_process */ "child_process"));
|
|
319
|
-
const os = __importStar(__webpack_require__(/*! os */ "os"));
|
|
320
|
-
const module_1 = __webpack_require__(/*! module */ "module");
|
|
321
319
|
const progress_1 = __importDefault(__webpack_require__(/*! progress */ "./node_modules/progress/index.js"));
|
|
322
320
|
const Transpiler = __importStar(__webpack_require__(/*! @abaplint/transpiler */ "./node_modules/@abaplint/transpiler/build/src/index.js"));
|
|
323
|
-
const abaplint = __importStar(__webpack_require__(/*! @abaplint/core */ "./node_modules/@abaplint/core/build/src/index.js"));
|
|
324
321
|
const config_1 = __webpack_require__(/*! ./config */ "./build/config.js");
|
|
325
322
|
const file_operations_1 = __webpack_require__(/*! ./file_operations */ "./build/file_operations.js");
|
|
326
|
-
const
|
|
327
|
-
const
|
|
323
|
+
const libraries_1 = __webpack_require__(/*! ./libraries */ "./build/libraries.js");
|
|
324
|
+
const write_objects_1 = __webpack_require__(/*! ./write_objects */ "./build/write_objects.js");
|
|
328
325
|
class Progress {
|
|
329
326
|
bar;
|
|
330
327
|
set(total, _text) {
|
|
@@ -335,142 +332,30 @@ class Progress {
|
|
|
335
332
|
this.bar.render();
|
|
336
333
|
}
|
|
337
334
|
}
|
|
338
|
-
async function loadLib(config) {
|
|
339
|
-
const files = [];
|
|
340
|
-
for (const lib of config.libs || []) {
|
|
341
|
-
let dir = "";
|
|
342
|
-
let cleanupFolder = false;
|
|
343
|
-
const folder = (0, lib_folder_1.resolveLibFolder)(lib.folder, process.cwd());
|
|
344
|
-
if (folder !== undefined && fs.existsSync(folder)) {
|
|
345
|
-
console.log("From folder: " + folder);
|
|
346
|
-
dir = folder;
|
|
347
|
-
}
|
|
348
|
-
else {
|
|
349
|
-
if (lib.url === undefined || lib.url === "") {
|
|
350
|
-
if (folder === undefined) {
|
|
351
|
-
throw new Error("Library must define a non-empty url or an existing folder");
|
|
352
|
-
}
|
|
353
|
-
throw new Error("Library folder not found: " + folder);
|
|
354
|
-
}
|
|
355
|
-
console.log("Clone: " + lib.url);
|
|
356
|
-
dir = fs.mkdtempSync(path.join(os.tmpdir(), "abap_transpile-"));
|
|
357
|
-
const args = (0, git_clone_1.buildGitCloneArguments)(lib.url);
|
|
358
|
-
childProcess.execFileSync("git", args, { cwd: dir, stdio: "inherit" });
|
|
359
|
-
cleanupFolder = true;
|
|
360
|
-
}
|
|
361
|
-
let patterns = ["/src/**"];
|
|
362
|
-
if (lib.files !== undefined && typeof lib.files === "string" && lib.files !== "") {
|
|
363
|
-
patterns = [lib.files];
|
|
364
|
-
}
|
|
365
|
-
else if (Array.isArray(lib.files)) {
|
|
366
|
-
patterns = lib.files;
|
|
367
|
-
}
|
|
368
|
-
const excludeFilters = (lib.exclude_filter ?? []).map(pattern => new RegExp(pattern, "i"));
|
|
369
|
-
const filesToRead = [];
|
|
370
|
-
for (const pattern of patterns) {
|
|
371
|
-
for (const filename of file_operations_1.FileOperations.globSync(dir + pattern)) {
|
|
372
|
-
if (filename.endsWith(".clas.testclasses.abap")) {
|
|
373
|
-
continue;
|
|
374
|
-
}
|
|
375
|
-
else if (excludeFilters.length > 0 && excludeFilters.some(a => a.test(filename)) === true) {
|
|
376
|
-
continue;
|
|
377
|
-
}
|
|
378
|
-
filesToRead.push(filename);
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
files.push(...await file_operations_1.FileOperations.readAllFiles(filesToRead, ""));
|
|
382
|
-
console.log("\t" + filesToRead.length + " files added from lib");
|
|
383
|
-
if (cleanupFolder === true) {
|
|
384
|
-
file_operations_1.FileOperations.deleteFolderRecursive(dir);
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
return files;
|
|
388
|
-
}
|
|
389
|
-
async function writeObjects(outputFiles, config, outputFolder, files) {
|
|
390
|
-
const writeSourceMaps = config.write_source_map || false;
|
|
391
|
-
const filesToWrite = [];
|
|
392
|
-
for (const output of outputFiles) {
|
|
393
|
-
const type = output.object.type.toUpperCase();
|
|
394
|
-
let contents = output.chunk.getCode();
|
|
395
|
-
// PROG output gets a runtime bootstrap line prepended, which shifts every
|
|
396
|
-
// generated line down by one - the source map must account for this offset
|
|
397
|
-
let generatedLineOffset = 0;
|
|
398
|
-
if (type === "PROG") {
|
|
399
|
-
// hmm, will this work for INCLUDEs ?
|
|
400
|
-
contents = `if (!globalThis.abap) await import("./_init.mjs");\n` + contents;
|
|
401
|
-
generatedLineOffset = 1;
|
|
402
|
-
}
|
|
403
|
-
if (writeSourceMaps === true
|
|
404
|
-
&& (type === "PROG" || type === "FUGR" || type === "CLAS")) {
|
|
405
|
-
const name = output.filename + ".map";
|
|
406
|
-
// SourceMappingUrl needs to be percent-encoded, ref https://github.com/microsoft/TypeScript/issues/40951
|
|
407
|
-
contents = contents + `\n//# sourceMappingURL=` + name.replace(/%/g, "%25").replace(/#/g, "%23");
|
|
408
|
-
// map the bare abap filename each mapping carries to its path on disk;
|
|
409
|
-
// source map "sources" are URLs, so always forward slashes, also on Windows
|
|
410
|
-
const sourcePaths = {};
|
|
411
|
-
for (const f of files) {
|
|
412
|
-
if (f.relative === undefined) {
|
|
413
|
-
continue;
|
|
414
|
-
}
|
|
415
|
-
const rel = f.relative.split(path.sep).join("/");
|
|
416
|
-
sourcePaths[f.filename] = rel === "" ? f.filename : `${rel}/${f.filename}`;
|
|
417
|
-
}
|
|
418
|
-
const map = output.chunk.getMap(output.filename, { generatedLineOffset, sourcePaths });
|
|
419
|
-
filesToWrite.push({ path: outputFolder + path.sep + name, contents: map });
|
|
420
|
-
}
|
|
421
|
-
filesToWrite.push({ path: outputFolder + path.sep + output.filename, contents });
|
|
422
|
-
}
|
|
423
|
-
await file_operations_1.FileOperations.writeFiles(filesToWrite);
|
|
424
|
-
}
|
|
425
|
-
const PLUGIN_MODULE = "@abaplint/transpiler-extras";
|
|
426
|
-
function loadPlugin() {
|
|
427
|
-
// createRequire so the plugin resolves from the project consuming the CLI, also after webpacking
|
|
428
|
-
const projectRequire = (0, module_1.createRequire)(path.join(process.cwd(), "package.json"));
|
|
429
|
-
try {
|
|
430
|
-
projectRequire.resolve(PLUGIN_MODULE);
|
|
431
|
-
}
|
|
432
|
-
catch {
|
|
433
|
-
// plugin package not installed
|
|
434
|
-
return undefined;
|
|
435
|
-
}
|
|
436
|
-
const plugin = projectRequire(PLUGIN_MODULE).plugin;
|
|
437
|
-
if (plugin === undefined) {
|
|
438
|
-
throw new Error(PLUGIN_MODULE + " does not export a plugin");
|
|
439
|
-
}
|
|
440
|
-
console.log("Plugin loaded: " + PLUGIN_MODULE + ", object types: " + plugin.objectTypes().join(", "));
|
|
441
|
-
console.log("Note this requires license for commercial use");
|
|
442
|
-
return plugin;
|
|
443
|
-
}
|
|
444
335
|
async function build(config, files) {
|
|
445
|
-
const
|
|
336
|
+
const libraries = await (0, libraries_1.loadLibraries)(config);
|
|
446
337
|
const options = { ...config.options };
|
|
447
338
|
if (config.write_source_map !== true) {
|
|
448
339
|
// Do not pay to allocate and copy mappings that the CLI will not write.
|
|
449
340
|
options.ignoreSourceMap = true;
|
|
450
341
|
}
|
|
451
|
-
const t = new Transpiler.Transpiler(options
|
|
452
|
-
const reg =
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
}
|
|
456
|
-
for (const l of libFiles) {
|
|
457
|
-
reg.addDependency(new abaplint.MemoryFile(l.filename, l.contents));
|
|
458
|
-
}
|
|
459
|
-
const output = await t.run(reg, new Progress());
|
|
460
|
-
return output;
|
|
342
|
+
const t = new Transpiler.Transpiler(options);
|
|
343
|
+
const { reg, folders, sources } = (0, libraries_1.libraryRegistry)(files, libraries);
|
|
344
|
+
const output = await t.run(reg, new Progress(), folders);
|
|
345
|
+
return { output, sources };
|
|
461
346
|
}
|
|
462
347
|
async function run() {
|
|
463
348
|
console.log("Transpiler CLI");
|
|
464
349
|
const config = config_1.TranspilerConfig.find(process.argv[2]);
|
|
465
350
|
const files = await file_operations_1.FileOperations.loadFiles(config);
|
|
466
351
|
console.log("\nBuilding");
|
|
467
|
-
const output = await build(config, files);
|
|
352
|
+
const { output, sources } = await build(config, files);
|
|
468
353
|
console.log("\nOutput");
|
|
469
354
|
const outputFolder = config.output_folder;
|
|
470
355
|
if (!fs.existsSync(outputFolder)) {
|
|
471
|
-
fs.mkdirSync(outputFolder);
|
|
356
|
+
fs.mkdirSync(outputFolder, { recursive: true });
|
|
472
357
|
}
|
|
473
|
-
await writeObjects(output.objects, config,
|
|
358
|
+
await (0, write_objects_1.writeObjects)(output.objects, config, sources);
|
|
474
359
|
console.log(output.objects.length + " objects written to disk");
|
|
475
360
|
if (config.write_unit_tests === true) {
|
|
476
361
|
// breaking change? rename this output file,
|
|
@@ -553,6 +438,267 @@ function resolveLibFolder(folder, cwd) {
|
|
|
553
438
|
|
|
554
439
|
/***/ },
|
|
555
440
|
|
|
441
|
+
/***/ "./build/libraries.js"
|
|
442
|
+
/*!****************************!*\
|
|
443
|
+
!*** ./build/libraries.js ***!
|
|
444
|
+
\****************************/
|
|
445
|
+
(__unused_webpack_module, exports, __webpack_require__) {
|
|
446
|
+
|
|
447
|
+
"use strict";
|
|
448
|
+
|
|
449
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
450
|
+
if (k2 === undefined) k2 = k;
|
|
451
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
452
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
453
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
454
|
+
}
|
|
455
|
+
Object.defineProperty(o, k2, desc);
|
|
456
|
+
}) : (function(o, m, k, k2) {
|
|
457
|
+
if (k2 === undefined) k2 = k;
|
|
458
|
+
o[k2] = m[k];
|
|
459
|
+
}));
|
|
460
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
461
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
462
|
+
}) : function(o, v) {
|
|
463
|
+
o["default"] = v;
|
|
464
|
+
});
|
|
465
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
466
|
+
var ownKeys = function(o) {
|
|
467
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
468
|
+
var ar = [];
|
|
469
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
470
|
+
return ar;
|
|
471
|
+
};
|
|
472
|
+
return ownKeys(o);
|
|
473
|
+
};
|
|
474
|
+
return function (mod) {
|
|
475
|
+
if (mod && mod.__esModule) return mod;
|
|
476
|
+
var result = {};
|
|
477
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
478
|
+
__setModuleDefault(result, mod);
|
|
479
|
+
return result;
|
|
480
|
+
};
|
|
481
|
+
})();
|
|
482
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
483
|
+
exports.libraryNames = libraryNames;
|
|
484
|
+
exports.loadLibraries = loadLibraries;
|
|
485
|
+
exports.libraryRegistry = libraryRegistry;
|
|
486
|
+
const fs = __importStar(__webpack_require__(/*! fs */ "fs"));
|
|
487
|
+
const path = __importStar(__webpack_require__(/*! path */ "path"));
|
|
488
|
+
const childProcess = __importStar(__webpack_require__(/*! child_process */ "child_process"));
|
|
489
|
+
const os = __importStar(__webpack_require__(/*! os */ "os"));
|
|
490
|
+
const abaplint = __importStar(__webpack_require__(/*! @abaplint/core */ "./node_modules/@abaplint/core/build/src/index.js"));
|
|
491
|
+
const file_operations_1 = __webpack_require__(/*! ./file_operations */ "./build/file_operations.js");
|
|
492
|
+
const git_clone_1 = __webpack_require__(/*! ./git_clone */ "./build/git_clone.js");
|
|
493
|
+
const lib_folder_1 = __webpack_require__(/*! ./lib_folder */ "./build/lib_folder.js");
|
|
494
|
+
function libraryNames(libs) {
|
|
495
|
+
const used = new Set(["project"]);
|
|
496
|
+
return libs.map(lib => {
|
|
497
|
+
const source = (lib.url || lib.folder || "").replace(/\\/g, "/").replace(/\/+$/, "");
|
|
498
|
+
const name = lib.name ?? source.substring(Math.max(source.lastIndexOf("/"), source.lastIndexOf(":")) + 1)
|
|
499
|
+
.replace(/\.git$/i, "");
|
|
500
|
+
if (typeof name !== "string" || name.length === 0 || name === "." || name === ".."
|
|
501
|
+
|| /[<>:"/\\|?*\u0000-\u001f]/.test(name) || /[. ]$/.test(name)
|
|
502
|
+
|| /^(con|prn|aux|nul|com[1-9¹²³]|lpt[1-9¹²³])(\.|$)/i.test(name)) {
|
|
503
|
+
throw new Error("Invalid library name: " + JSON.stringify(name) + ". Set libs[].name to a valid folder name.");
|
|
504
|
+
}
|
|
505
|
+
if (used.has(name.toLowerCase())) {
|
|
506
|
+
throw new Error("Duplicate or reserved library name: " + name + ". Set a different libs[].name.");
|
|
507
|
+
}
|
|
508
|
+
used.add(name.toLowerCase());
|
|
509
|
+
return name;
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
async function loadLibraries(config) {
|
|
513
|
+
const libs = config.libs || [];
|
|
514
|
+
const names = libraryNames(libs);
|
|
515
|
+
const result = [];
|
|
516
|
+
for (const [index, lib] of libs.entries()) {
|
|
517
|
+
let dir;
|
|
518
|
+
let cleanupFolder = false;
|
|
519
|
+
const folder = (0, lib_folder_1.resolveLibFolder)(lib.folder, process.cwd());
|
|
520
|
+
if (folder !== undefined && fs.existsSync(folder)) {
|
|
521
|
+
console.log("From folder: " + folder);
|
|
522
|
+
dir = folder;
|
|
523
|
+
}
|
|
524
|
+
else {
|
|
525
|
+
if (!lib.url) {
|
|
526
|
+
throw new Error(folder === undefined
|
|
527
|
+
? "Library must define a non-empty url or an existing folder"
|
|
528
|
+
: "Library folder not found: " + folder);
|
|
529
|
+
}
|
|
530
|
+
console.log("Clone: " + lib.url);
|
|
531
|
+
dir = fs.mkdtempSync(path.join(os.tmpdir(), "abap_transpile-"));
|
|
532
|
+
cleanupFolder = true;
|
|
533
|
+
}
|
|
534
|
+
try {
|
|
535
|
+
if (cleanupFolder) {
|
|
536
|
+
childProcess.execFileSync("git", (0, git_clone_1.buildGitCloneArguments)(lib.url), { cwd: dir, stdio: "inherit" });
|
|
537
|
+
}
|
|
538
|
+
const patterns = typeof lib.files === "string" && lib.files !== "" ? [lib.files]
|
|
539
|
+
: Array.isArray(lib.files) ? lib.files : ["/src/**"];
|
|
540
|
+
const excludeFilters = (lib.exclude_filter ?? []).map(pattern => new RegExp(pattern, "i"));
|
|
541
|
+
const filesToRead = new Set();
|
|
542
|
+
for (const pattern of patterns) {
|
|
543
|
+
for (const filename of file_operations_1.FileOperations.globSync(dir + pattern)) {
|
|
544
|
+
if (filename.endsWith(".clas.testclasses.abap") || excludeFilters.some(filter => filter.test(filename))) {
|
|
545
|
+
continue;
|
|
546
|
+
}
|
|
547
|
+
filesToRead.add(filename);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
const files = await file_operations_1.FileOperations.readAllFiles([...filesToRead], config.output_folder);
|
|
551
|
+
result.push({ name: names[index], files });
|
|
552
|
+
console.log("\t" + files.length + " files added from lib");
|
|
553
|
+
}
|
|
554
|
+
finally {
|
|
555
|
+
if (cleanupFolder) {
|
|
556
|
+
file_operations_1.FileOperations.deleteFolderRecursive(dir);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
return result;
|
|
561
|
+
}
|
|
562
|
+
function libraryRegistry(files, libraries) {
|
|
563
|
+
const reg = new abaplint.Registry();
|
|
564
|
+
const folders = new Map();
|
|
565
|
+
const objects = new Map();
|
|
566
|
+
const sources = new Map();
|
|
567
|
+
// Libraries first: addFile() then replaces a dependency object with the project's object.
|
|
568
|
+
for (const lib of libraries) {
|
|
569
|
+
for (const file of lib.files) {
|
|
570
|
+
const memory = new abaplint.MemoryFile(file.filename, file.contents);
|
|
571
|
+
const type = memory.getObjectType()?.toUpperCase();
|
|
572
|
+
if (type === undefined || file.filename.split(".").length <= 2) {
|
|
573
|
+
continue;
|
|
574
|
+
}
|
|
575
|
+
const key = type + ":" + memory.getObjectName().toUpperCase();
|
|
576
|
+
const owner = objects.get(key);
|
|
577
|
+
// abapGit repeats package.devc.xml across repositories; the registry keeps the last copy.
|
|
578
|
+
if (key !== "DEVC:PACKAGE" && owner !== undefined && owner !== lib.name) {
|
|
579
|
+
throw new Error("Ambiguous dependency object " + key + " in " + owner + " and " + lib.name);
|
|
580
|
+
}
|
|
581
|
+
objects.set(key, lib.name);
|
|
582
|
+
reg.addDependency(memory);
|
|
583
|
+
folders.set(file.filename.toLowerCase(), lib.name);
|
|
584
|
+
sources.set(file.filename.toLowerCase(), file);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
for (const file of files) {
|
|
588
|
+
reg.addFile(new abaplint.MemoryFile(file.filename, file.contents));
|
|
589
|
+
folders.set(file.filename.toLowerCase(), "project");
|
|
590
|
+
sources.set(file.filename.toLowerCase(), file);
|
|
591
|
+
}
|
|
592
|
+
return { reg, folders, sources: [...sources.values()] };
|
|
593
|
+
}
|
|
594
|
+
//# sourceMappingURL=libraries.js.map
|
|
595
|
+
|
|
596
|
+
/***/ },
|
|
597
|
+
|
|
598
|
+
/***/ "./build/write_objects.js"
|
|
599
|
+
/*!********************************!*\
|
|
600
|
+
!*** ./build/write_objects.js ***!
|
|
601
|
+
\********************************/
|
|
602
|
+
(__unused_webpack_module, exports, __webpack_require__) {
|
|
603
|
+
|
|
604
|
+
"use strict";
|
|
605
|
+
|
|
606
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
607
|
+
if (k2 === undefined) k2 = k;
|
|
608
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
609
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
610
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
611
|
+
}
|
|
612
|
+
Object.defineProperty(o, k2, desc);
|
|
613
|
+
}) : (function(o, m, k, k2) {
|
|
614
|
+
if (k2 === undefined) k2 = k;
|
|
615
|
+
o[k2] = m[k];
|
|
616
|
+
}));
|
|
617
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
618
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
619
|
+
}) : function(o, v) {
|
|
620
|
+
o["default"] = v;
|
|
621
|
+
});
|
|
622
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
623
|
+
var ownKeys = function(o) {
|
|
624
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
625
|
+
var ar = [];
|
|
626
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
627
|
+
return ar;
|
|
628
|
+
};
|
|
629
|
+
return ownKeys(o);
|
|
630
|
+
};
|
|
631
|
+
return function (mod) {
|
|
632
|
+
if (mod && mod.__esModule) return mod;
|
|
633
|
+
var result = {};
|
|
634
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
635
|
+
__setModuleDefault(result, mod);
|
|
636
|
+
return result;
|
|
637
|
+
};
|
|
638
|
+
})();
|
|
639
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
640
|
+
exports.writeObjects = writeObjects;
|
|
641
|
+
const path = __importStar(__webpack_require__(/*! path */ "path"));
|
|
642
|
+
const url_1 = __webpack_require__(/*! url */ "url");
|
|
643
|
+
const transpiler_1 = __webpack_require__(/*! @abaplint/transpiler */ "./node_modules/@abaplint/transpiler/build/src/index.js");
|
|
644
|
+
const file_operations_1 = __webpack_require__(/*! ./file_operations */ "./build/file_operations.js");
|
|
645
|
+
async function writeObjects(outputFiles, config, files) {
|
|
646
|
+
const root = path.resolve(config.output_folder);
|
|
647
|
+
const filesToWrite = [];
|
|
648
|
+
const destinations = new Set();
|
|
649
|
+
const sources = new Map(files.map(file => [file.filename.toLowerCase(), file]));
|
|
650
|
+
const add = (filename, contents) => {
|
|
651
|
+
const target = path.resolve(root, filename);
|
|
652
|
+
const relative = path.relative(root, target);
|
|
653
|
+
if (relative === "" || relative.startsWith(".." + path.sep) || relative === ".." || path.isAbsolute(relative)) {
|
|
654
|
+
throw new Error("Output file escapes output_folder: " + filename);
|
|
655
|
+
}
|
|
656
|
+
const key = target.toLowerCase();
|
|
657
|
+
if (destinations.has(key)) {
|
|
658
|
+
throw new Error("Conflicting output file: " + filename);
|
|
659
|
+
}
|
|
660
|
+
destinations.add(key);
|
|
661
|
+
filesToWrite.push({ path: target, contents });
|
|
662
|
+
};
|
|
663
|
+
for (const output of outputFiles) {
|
|
664
|
+
const type = output.object.type.toUpperCase();
|
|
665
|
+
let contents = output.chunk.getCode();
|
|
666
|
+
let generatedLineOffset = 0;
|
|
667
|
+
if (type === "PROG") {
|
|
668
|
+
contents = 'if (!globalThis.abap) await import("' + (0, transpiler_1.importPath)(output.filename, "_init.mjs") + '");\n' + contents;
|
|
669
|
+
generatedLineOffset = 1;
|
|
670
|
+
}
|
|
671
|
+
if (config.write_source_map === true && (type === "PROG" || type === "FUGR" || type === "CLAS")) {
|
|
672
|
+
const name = output.filename + ".map";
|
|
673
|
+
contents += "\n//# sourceMappingURL=" + encodeURIComponent(path.basename(name));
|
|
674
|
+
const sourcePaths = {};
|
|
675
|
+
const sourceContents = {};
|
|
676
|
+
const mapDirectory = path.dirname(path.join(root, name));
|
|
677
|
+
for (const filename of new Set(output.chunk.mappings.map(mapping => mapping.source))) {
|
|
678
|
+
const file = sources.get(filename.toLowerCase());
|
|
679
|
+
if (file === undefined) {
|
|
680
|
+
continue;
|
|
681
|
+
}
|
|
682
|
+
if (file.relative !== undefined) {
|
|
683
|
+
const source = path.resolve(root, file.relative, file.filename);
|
|
684
|
+
const relative = path.relative(mapDirectory, source);
|
|
685
|
+
// Sources on another Windows drive cannot be expressed as relative paths.
|
|
686
|
+
sourcePaths[filename] = path.isAbsolute(relative) ? (0, url_1.pathToFileURL)(source).href
|
|
687
|
+
: relative.split(path.sep).map(segment => encodeURIComponent(segment)).join("/");
|
|
688
|
+
}
|
|
689
|
+
// Include sources for local and cloned libraries; clones are removed before emission.
|
|
690
|
+
sourceContents[filename] = file.contents;
|
|
691
|
+
}
|
|
692
|
+
add(name, output.chunk.getMap(path.basename(output.filename), { generatedLineOffset, sourcePaths, sourceContents }));
|
|
693
|
+
}
|
|
694
|
+
add(output.filename, contents);
|
|
695
|
+
}
|
|
696
|
+
await file_operations_1.FileOperations.writeFiles(filesToWrite);
|
|
697
|
+
}
|
|
698
|
+
//# sourceMappingURL=write_objects.js.map
|
|
699
|
+
|
|
700
|
+
/***/ },
|
|
701
|
+
|
|
556
702
|
/***/ "./node_modules/@abaplint/core/build/src/abap/1_lexer/lexer.js"
|
|
557
703
|
/*!*********************************************************************!*\
|
|
558
704
|
!*** ./node_modules/@abaplint/core/build/src/abap/1_lexer/lexer.js ***!
|
|
@@ -10941,7 +11087,7 @@ class StringTemplateFormatting extends combi_1.Expression {
|
|
|
10941
11087
|
const alpha = (0, combi_1.ver)(version_1.Release.v740sp02, (0, combi_1.seq)("ALPHA =", alphaOptions), { also: combi_1.AlsoIn.OpenABAP });
|
|
10942
11088
|
const xsd = (0, combi_1.ver)(version_1.Release.v740sp02, (0, combi_1.seq)("XSD =", zeroXSDOptions));
|
|
10943
11089
|
const country = (0, combi_1.seq)("COUNTRY =", _1.Source);
|
|
10944
|
-
const formatting = (0, combi_1.altPrio)((0, combi_1.seq)("TIME =", dateTimeOptions), (0, combi_1.seq)("DATE =", dateTimeOptions), (0, combi_1.seq)("CASE =", caseOptions), (0, combi_1.seq)("
|
|
11090
|
+
const formatting = (0, combi_1.altPrio)((0, combi_1.seq)("TIME =", dateTimeOptions), (0, combi_1.seq)("DATE =", dateTimeOptions), (0, combi_1.seq)("CASE =", caseOptions), (0, combi_1.seq)("ZERO =", zeroXSDOptions), xsd, (0, combi_1.seq)("STYLE =", styleOptions), (0, combi_1.seq)("CURRENCY =", _1.Source), (0, combi_1.per)(sign, number, decimals, width, pad, alpha, align, country, (0, combi_1.seq)("EXPONENT =", _1.Source)), (0, combi_1.per)(timezone, timestamp));
|
|
10945
11091
|
return formatting;
|
|
10946
11092
|
}
|
|
10947
11093
|
}
|
|
@@ -30673,12 +30819,15 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
30673
30819
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
30674
30820
|
exports.Compare = void 0;
|
|
30675
30821
|
const Expressions = __importStar(__webpack_require__(/*! ../../2_statements/expressions */ "./node_modules/@abaplint/core/build/src/abap/2_statements/expressions/index.js"));
|
|
30822
|
+
const nodes_1 = __webpack_require__(/*! ../../nodes */ "./node_modules/@abaplint/core/build/src/abap/nodes/index.js");
|
|
30676
30823
|
const source_1 = __webpack_require__(/*! ./source */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/source.js");
|
|
30677
30824
|
const method_call_chain_1 = __webpack_require__(/*! ./method_call_chain */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/method_call_chain.js");
|
|
30678
30825
|
const source_field_symbol_1 = __webpack_require__(/*! ./source_field_symbol */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/source_field_symbol.js");
|
|
30679
30826
|
const _syntax_input_1 = __webpack_require__(/*! ../_syntax_input */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/_syntax_input.js");
|
|
30680
30827
|
const basic_1 = __webpack_require__(/*! ../../types/basic */ "./node_modules/@abaplint/core/build/src/abap/types/basic/index.js");
|
|
30681
30828
|
const _type_utils_1 = __webpack_require__(/*! ../_type_utils */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/_type_utils.js");
|
|
30829
|
+
const _builtin_1 = __webpack_require__(/*! ../_builtin */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/_builtin.js");
|
|
30830
|
+
const _object_oriented_1 = __webpack_require__(/*! ../_object_oriented */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/_object_oriented.js");
|
|
30682
30831
|
class Compare {
|
|
30683
30832
|
static runSyntax(node, input) {
|
|
30684
30833
|
var _a;
|
|
@@ -30693,6 +30842,11 @@ class Compare {
|
|
|
30693
30842
|
for (const t of node.findDirectExpressions(Expressions.MethodCallChain)) {
|
|
30694
30843
|
method_call_chain_1.MethodCallChain.runSyntax(t, input);
|
|
30695
30844
|
}
|
|
30845
|
+
const initialMessage = this.checkInitialOperand(node, input);
|
|
30846
|
+
if (initialMessage !== undefined) {
|
|
30847
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), initialMessage));
|
|
30848
|
+
return;
|
|
30849
|
+
}
|
|
30696
30850
|
const typeUtils = new _type_utils_1.TypeUtils(input.scope);
|
|
30697
30851
|
const compareOperator = (_a = node.findDirectExpression(Expressions.CompareOperator)) === null || _a === void 0 ? void 0 : _a.concatTokens().toUpperCase();
|
|
30698
30852
|
if (compareOperator === "CS"
|
|
@@ -30716,6 +30870,46 @@ class Compare {
|
|
|
30716
30870
|
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
|
|
30717
30871
|
}
|
|
30718
30872
|
}
|
|
30873
|
+
// a built-in function with a character-like result cannot be the operand of IS [NOT] INITIAL,
|
|
30874
|
+
// "Unexpected operator IS" on a system, while one with a numeric result, lines( ), can
|
|
30875
|
+
static checkInitialOperand(node, input) {
|
|
30876
|
+
var _a, _b, _c, _d;
|
|
30877
|
+
if (input.scope.getOpenABAP()) {
|
|
30878
|
+
return undefined;
|
|
30879
|
+
}
|
|
30880
|
+
const tokens = node.getChildren().filter(c => c instanceof nodes_1.TokenNode).map(c => c.getFirstToken().getStr().toUpperCase());
|
|
30881
|
+
if (tokens.includes("IS") === false || tokens[tokens.length - 1] !== "INITIAL") {
|
|
30882
|
+
return undefined;
|
|
30883
|
+
}
|
|
30884
|
+
const chain = (_a = node.findDirectExpression(Expressions.Source)) === null || _a === void 0 ? void 0 : _a.getChildren();
|
|
30885
|
+
// xsdbool( ) and boolc( ) are their own form in the Source grammar, a condition in parentheses
|
|
30886
|
+
const first = (_b = chain === null || chain === void 0 ? void 0 : chain[0]) === null || _b === void 0 ? void 0 : _b.getFirstToken().getStr().toUpperCase();
|
|
30887
|
+
if ((chain === null || chain === void 0 ? void 0 : chain.length) === 4 && chain[0] instanceof nodes_1.TokenNode && (first === "XSDBOOL" || first === "BOOLC")) {
|
|
30888
|
+
return `Built-in function "${chain[0].getFirstToken().getStr()}" cannot be the operand of IS INITIAL`;
|
|
30889
|
+
}
|
|
30890
|
+
if ((chain === null || chain === void 0 ? void 0 : chain.length) !== 1 || !(chain[0] instanceof nodes_1.ExpressionNode) || !(chain[0].get() instanceof Expressions.MethodCallChain)) {
|
|
30891
|
+
return undefined;
|
|
30892
|
+
}
|
|
30893
|
+
const calls = chain[0].getChildren();
|
|
30894
|
+
if (calls.length !== 1 || !(calls[0] instanceof nodes_1.ExpressionNode) || !(calls[0].get() instanceof Expressions.MethodCall)) {
|
|
30895
|
+
return undefined;
|
|
30896
|
+
}
|
|
30897
|
+
const name = (_c = calls[0].findDirectExpression(Expressions.MethodName)) === null || _c === void 0 ? void 0 : _c.concatTokens();
|
|
30898
|
+
const builtin = _builtin_1.BuiltIn.searchBuiltin(name);
|
|
30899
|
+
if (name === undefined || builtin === undefined) {
|
|
30900
|
+
return undefined;
|
|
30901
|
+
}
|
|
30902
|
+
// a method of the same name hides the built-in function
|
|
30903
|
+
const enclosing = input.scope.findClassDefinition(input.scope.getEnclosingClassName());
|
|
30904
|
+
if (enclosing !== undefined && new _object_oriented_1.ObjectOriented(input.scope).searchMethodName(enclosing, name).method !== undefined) {
|
|
30905
|
+
return undefined;
|
|
30906
|
+
}
|
|
30907
|
+
const returning = (_d = builtin.getParameters().getReturning()) === null || _d === void 0 ? void 0 : _d.getType();
|
|
30908
|
+
if (returning instanceof basic_1.StringType || returning instanceof basic_1.CharacterType) {
|
|
30909
|
+
return `Built-in function "${name}" cannot be the operand of IS INITIAL`;
|
|
30910
|
+
}
|
|
30911
|
+
return undefined;
|
|
30912
|
+
}
|
|
30719
30913
|
}
|
|
30720
30914
|
exports.Compare = Compare;
|
|
30721
30915
|
//# sourceMappingURL=compare.js.map
|
|
@@ -32488,6 +32682,9 @@ class FormParam {
|
|
|
32488
32682
|
else if (typeName === "P" && bfound instanceof basic_1.PackedType) {
|
|
32489
32683
|
bfound = basic_1.PGenericType.get();
|
|
32490
32684
|
}
|
|
32685
|
+
else if (typeName === "N" && bfound instanceof basic_1.NumericType) {
|
|
32686
|
+
bfound = basic_1.NGenericType.get();
|
|
32687
|
+
}
|
|
32491
32688
|
}
|
|
32492
32689
|
if (nameToken && bfound) {
|
|
32493
32690
|
return new _typed_identifier_1.TypedIdentifier(nameToken, input.filename, bfound, ["form_parameter" /* IdentifierMeta.FormParameter */]);
|
|
@@ -33874,6 +34071,9 @@ class MethodParam {
|
|
|
33874
34071
|
else if (concat === "TYPE P" || concat.startsWith("TYPE P ")) {
|
|
33875
34072
|
return new _typed_identifier_1.TypedIdentifier(name.getFirstToken(), input.filename, basic_1.PGenericType.get(), meta);
|
|
33876
34073
|
}
|
|
34074
|
+
else if (concat === "TYPE N" || concat.startsWith("TYPE N ")) {
|
|
34075
|
+
return new _typed_identifier_1.TypedIdentifier(name.getFirstToken(), input.filename, basic_1.NGenericType.get(), meta);
|
|
34076
|
+
}
|
|
33877
34077
|
const found = new basic_types_1.BasicTypes(input).parseType(type);
|
|
33878
34078
|
if (found) {
|
|
33879
34079
|
return new _typed_identifier_1.TypedIdentifier(name.getFirstToken(), input.filename, found, meta);
|
|
@@ -40576,9 +40776,9 @@ class CreateObject {
|
|
|
40576
40776
|
if (name === undefined) {
|
|
40577
40777
|
continue;
|
|
40578
40778
|
}
|
|
40579
|
-
const source = p.findDirectExpression(Expressions.Source);
|
|
40580
|
-
const sourceType = source_1.Source.runSyntax(source, input);
|
|
40581
40779
|
const found = allImporting === null || allImporting === void 0 ? void 0 : allImporting.find(p => p.getName().toUpperCase() === name);
|
|
40780
|
+
const source = p.findDirectExpression(Expressions.Source);
|
|
40781
|
+
const sourceType = source_1.Source.runSyntax(source, input, found === null || found === void 0 ? void 0 : found.getType());
|
|
40582
40782
|
if (found === undefined) {
|
|
40583
40783
|
const message = `constructor parameter "${name}" does not exist`;
|
|
40584
40784
|
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
|
|
@@ -52035,6 +52235,7 @@ __exportStar(__webpack_require__(/*! ./generic_object_reference_type */ "./node_
|
|
|
52035
52235
|
__exportStar(__webpack_require__(/*! ./hex_type */ "./node_modules/@abaplint/core/build/src/abap/types/basic/hex_type.js"), exports);
|
|
52036
52236
|
__exportStar(__webpack_require__(/*! ./integer_type */ "./node_modules/@abaplint/core/build/src/abap/types/basic/integer_type.js"), exports);
|
|
52037
52237
|
__exportStar(__webpack_require__(/*! ./integer8_type */ "./node_modules/@abaplint/core/build/src/abap/types/basic/integer8_type.js"), exports);
|
|
52238
|
+
__exportStar(__webpack_require__(/*! ./ngeneric_type */ "./node_modules/@abaplint/core/build/src/abap/types/basic/ngeneric_type.js"), exports);
|
|
52038
52239
|
__exportStar(__webpack_require__(/*! ./numeric_generic_type */ "./node_modules/@abaplint/core/build/src/abap/types/basic/numeric_generic_type.js"), exports);
|
|
52039
52240
|
__exportStar(__webpack_require__(/*! ./numeric_type */ "./node_modules/@abaplint/core/build/src/abap/types/basic/numeric_type.js"), exports);
|
|
52040
52241
|
__exportStar(__webpack_require__(/*! ./object_reference_type */ "./node_modules/@abaplint/core/build/src/abap/types/basic/object_reference_type.js"), exports);
|
|
@@ -52143,6 +52344,39 @@ IntegerType.singletons = new Map();
|
|
|
52143
52344
|
|
|
52144
52345
|
/***/ },
|
|
52145
52346
|
|
|
52347
|
+
/***/ "./node_modules/@abaplint/core/build/src/abap/types/basic/ngeneric_type.js"
|
|
52348
|
+
/*!*********************************************************************************!*\
|
|
52349
|
+
!*** ./node_modules/@abaplint/core/build/src/abap/types/basic/ngeneric_type.js ***!
|
|
52350
|
+
\*********************************************************************************/
|
|
52351
|
+
(__unused_webpack_module, exports, __webpack_require__) {
|
|
52352
|
+
|
|
52353
|
+
"use strict";
|
|
52354
|
+
|
|
52355
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
52356
|
+
exports.NGenericType = void 0;
|
|
52357
|
+
const numeric_type_1 = __webpack_require__(/*! ./numeric_type */ "./node_modules/@abaplint/core/build/src/abap/types/basic/numeric_type.js");
|
|
52358
|
+
// "TYPE n" of a method or FORM parameter, where no length can be given.
|
|
52359
|
+
// It is a NumericType, so everything that handles n keeps treating it as such
|
|
52360
|
+
class NGenericType extends numeric_type_1.NumericType {
|
|
52361
|
+
static get() {
|
|
52362
|
+
return this.singleton;
|
|
52363
|
+
}
|
|
52364
|
+
constructor() {
|
|
52365
|
+
super(1);
|
|
52366
|
+
}
|
|
52367
|
+
toText() {
|
|
52368
|
+
return "```n```";
|
|
52369
|
+
}
|
|
52370
|
+
isGeneric() {
|
|
52371
|
+
return true;
|
|
52372
|
+
}
|
|
52373
|
+
}
|
|
52374
|
+
exports.NGenericType = NGenericType;
|
|
52375
|
+
NGenericType.singleton = new NGenericType();
|
|
52376
|
+
//# sourceMappingURL=ngeneric_type.js.map
|
|
52377
|
+
|
|
52378
|
+
/***/ },
|
|
52379
|
+
|
|
52146
52380
|
/***/ "./node_modules/@abaplint/core/build/src/abap/types/basic/numeric_generic_type.js"
|
|
52147
52381
|
/*!****************************************************************************************!*\
|
|
52148
52382
|
!*** ./node_modules/@abaplint/core/build/src/abap/types/basic/numeric_generic_type.js ***!
|
|
@@ -71037,7 +71271,7 @@ class Registry {
|
|
|
71037
71271
|
}
|
|
71038
71272
|
static abaplintVersion() {
|
|
71039
71273
|
// magic, see build script "version.js"
|
|
71040
|
-
return "2.120.
|
|
71274
|
+
return "2.120.71";
|
|
71041
71275
|
}
|
|
71042
71276
|
getDDICReferences() {
|
|
71043
71277
|
return this.ddicReferences;
|
|
@@ -73726,7 +73960,7 @@ exports.CDSCheckSyntaxConf = CDSCheckSyntaxConf;
|
|
|
73726
73960
|
const KNOWN_QUAN_DATA_ELEMENTS = ["MENGE_D"];
|
|
73727
73961
|
const KNOWN_CURR_DATA_ELEMENTS = ["BWERT", "DZWERT"];
|
|
73728
73962
|
// Reserved names, cannot be used as element names, see DDIC table TRESE
|
|
73729
|
-
const RESERVED_ELEMENT_NAMES = ["BEGIN", "NUMBER", "POSITION"];
|
|
73963
|
+
const RESERVED_ELEMENT_NAMES = ["BEGIN", "NUMBER", "POSITION", "ZONE", "HANDLER", "SECTION"];
|
|
73730
73964
|
const MAX_LABEL_LENGTH = 40;
|
|
73731
73965
|
// Annotations which are not supported in CDS view entities
|
|
73732
73966
|
const VIEW_ENTITY_FORBIDDEN_ANNOTATIONS = ["Semantics.unitOfMeasure", "Semantics.currencyCode"];
|
|
@@ -80536,8 +80770,17 @@ ${indentation} output = ${uniqueName}.\n`;
|
|
|
80536
80770
|
const extra = (valueBody === null || valueBody === void 0 ? void 0 : valueBody.findDirectExpression(Expressions.For)) ? " " : "";
|
|
80537
80771
|
data = indentation + extra + `DATA ${structureName} LIKE LINE OF ${uniqueName}.\n`;
|
|
80538
80772
|
}
|
|
80773
|
+
// all rows are built in the same work area, a component a row leaves out must be initial,
|
|
80774
|
+
// not what an earlier row (or an earlier pass of a surrounding loop) put there
|
|
80775
|
+
const clearRows = valueBody !== undefined && this.valueRowsNeedClear(valueBody);
|
|
80776
|
+
const prefix = [];
|
|
80539
80777
|
for (const a of (valueBody === null || valueBody === void 0 ? void 0 : valueBody.getChildren()) || []) {
|
|
80540
80778
|
if (a.get() instanceof Expressions.FieldAssignment) {
|
|
80779
|
+
if (clearRows === true) {
|
|
80780
|
+
// the shared prefix applies to every following row, re-applied after each CLEAR
|
|
80781
|
+
prefix.push(a.concatTokens());
|
|
80782
|
+
continue;
|
|
80783
|
+
}
|
|
80541
80784
|
if (added === false) {
|
|
80542
80785
|
body += data;
|
|
80543
80786
|
added = true;
|
|
@@ -80561,6 +80804,16 @@ ${indentation} output = ${uniqueName}.\n`;
|
|
|
80561
80804
|
}
|
|
80562
80805
|
if (a instanceof nodes_1.ExpressionNode && a.get() instanceof Expressions.ValueBodyLine) {
|
|
80563
80806
|
let skip = false;
|
|
80807
|
+
if (clearRows === true && this.isStructuredValueRow(a)) {
|
|
80808
|
+
if (added === false) {
|
|
80809
|
+
body += data;
|
|
80810
|
+
added = true;
|
|
80811
|
+
}
|
|
80812
|
+
body += indentation + `CLEAR ${structureName}.\n`;
|
|
80813
|
+
for (const p of prefix) {
|
|
80814
|
+
body += indentation + structureName + "-" + p + ".\n";
|
|
80815
|
+
}
|
|
80816
|
+
}
|
|
80564
80817
|
for (const b of (a === null || a === void 0 ? void 0 : a.getChildren()) || []) {
|
|
80565
80818
|
if (b.get() instanceof Expressions.FieldAssignment) {
|
|
80566
80819
|
if (added === false) {
|
|
@@ -80639,6 +80892,39 @@ ${indentation} output = ${uniqueName}.\n`;
|
|
|
80639
80892
|
}
|
|
80640
80893
|
return undefined;
|
|
80641
80894
|
}
|
|
80895
|
+
/** a row that is built in the work area, ie. not "( source )" or "( LINES OF source )" */
|
|
80896
|
+
isStructuredValueRow(row) {
|
|
80897
|
+
return row.findDirectExpression(Expressions.Source) === undefined
|
|
80898
|
+
&& row.findDirectExpression(Expressions.ValueBodyLines) === undefined;
|
|
80899
|
+
}
|
|
80900
|
+
/** true if a row can observe a component that an earlier row, or an earlier pass of a surrounding loop,
|
|
80901
|
+
* left in the shared work area. Not the case if all rows assign the same components, and the shared
|
|
80902
|
+
* prefix is not changed between rows, eg. FOR rows or "( a = 1 b = 2 ) ( a = 3 b = 4 )" */
|
|
80903
|
+
valueRowsNeedClear(valueBody) {
|
|
80904
|
+
let shape = undefined;
|
|
80905
|
+
let rowSeen = false;
|
|
80906
|
+
for (const c of valueBody.getChildren()) {
|
|
80907
|
+
if (c.get() instanceof Expressions.FieldAssignment) {
|
|
80908
|
+
if (rowSeen === true) {
|
|
80909
|
+
return true;
|
|
80910
|
+
}
|
|
80911
|
+
}
|
|
80912
|
+
else if (c instanceof nodes_1.ExpressionNode
|
|
80913
|
+
&& c.get() instanceof Expressions.ValueBodyLine
|
|
80914
|
+
&& this.isStructuredValueRow(c)) {
|
|
80915
|
+
rowSeen = true;
|
|
80916
|
+
const current = c.findDirectExpressions(Expressions.FieldAssignment)
|
|
80917
|
+
.map(f => { var _a; return (_a = f.findDirectExpression(Expressions.FieldSub)) === null || _a === void 0 ? void 0 : _a.concatTokens().toUpperCase().replace(/\s/g, ""); })
|
|
80918
|
+
.sort()
|
|
80919
|
+
.join(",");
|
|
80920
|
+
if (shape !== undefined && shape !== current) {
|
|
80921
|
+
return true;
|
|
80922
|
+
}
|
|
80923
|
+
shape = current;
|
|
80924
|
+
}
|
|
80925
|
+
}
|
|
80926
|
+
return false;
|
|
80927
|
+
}
|
|
80642
80928
|
outlineLet(node, indentation, highSyntax, lowFile) {
|
|
80643
80929
|
var _a;
|
|
80644
80930
|
let ret = "";
|
|
@@ -95384,7 +95670,8 @@ class RedundantConversion {
|
|
|
95384
95670
|
key: "redundant_conversion",
|
|
95385
95671
|
title: "Redundant Conversion",
|
|
95386
95672
|
shortDescription: `Find redundant CONV expressions`,
|
|
95387
|
-
extendedInformation: `Reports CONV expressions whose operand already has the conversion's target type
|
|
95673
|
+
extendedInformation: `Reports CONV expressions whose operand already has the conversion's target type,
|
|
95674
|
+
including the result of a built-in function with a fixed result type, like to_upper( ) or strlen( ).`,
|
|
95388
95675
|
tags: [_irule_1.RuleTag.Quickfix],
|
|
95389
95676
|
badExample: `DATA text TYPE string.
|
|
95390
95677
|
text = CONV string( text ).`,
|
|
@@ -95421,7 +95708,8 @@ text = text.`,
|
|
|
95421
95708
|
if (structure === undefined) {
|
|
95422
95709
|
continue;
|
|
95423
95710
|
}
|
|
95424
|
-
|
|
95711
|
+
// recursive, a CONV can be the argument of a built-in function, which is itself a Source
|
|
95712
|
+
for (const source of structure.findAllExpressionsRecursive(Expressions.Source)) {
|
|
95425
95713
|
if (source.getFirstToken().getStr().toUpperCase() !== "CONV") {
|
|
95426
95714
|
continue;
|
|
95427
95715
|
}
|
|
@@ -95480,6 +95768,15 @@ text = text.`,
|
|
|
95480
95768
|
}
|
|
95481
95769
|
sourceType(source, scope) {
|
|
95482
95770
|
let context;
|
|
95771
|
+
// boolc( <condition> ) is not a MethodCallChain, xsdbool( ) has the same shape but is not reported
|
|
95772
|
+
const first = source.getFirstToken();
|
|
95773
|
+
if (first.getStr().toUpperCase() === "BOOLC"
|
|
95774
|
+
&& source.findDirectExpression(Expressions.Cond) !== undefined
|
|
95775
|
+
&& source.getChildren().length === 4
|
|
95776
|
+
&& scope.getData().references.some(reference => reference.referenceType === _reference_1.ReferenceType.BuiltinMethodReference
|
|
95777
|
+
&& reference.position.getStart().equals(first.getStart()))) {
|
|
95778
|
+
return basic_1.StringType.get();
|
|
95779
|
+
}
|
|
95483
95780
|
for (const child of source.getChildren()) {
|
|
95484
95781
|
if (!(child instanceof nodes_1.ExpressionNode)) {
|
|
95485
95782
|
continue;
|
|
@@ -95490,6 +95787,15 @@ text = text.`,
|
|
|
95490
95787
|
return undefined;
|
|
95491
95788
|
}
|
|
95492
95789
|
}
|
|
95790
|
+
else if (child.get() instanceof Expressions.MethodCallChain) {
|
|
95791
|
+
if (source.getChildren().length !== 1) {
|
|
95792
|
+
return undefined;
|
|
95793
|
+
}
|
|
95794
|
+
context = this.builtinResultType(child, scope);
|
|
95795
|
+
if (context === undefined) {
|
|
95796
|
+
return undefined;
|
|
95797
|
+
}
|
|
95798
|
+
}
|
|
95493
95799
|
else if (child.get() instanceof Expressions.Constant) {
|
|
95494
95800
|
context = this.infer(context, constant_1.Constant.runSyntax(child));
|
|
95495
95801
|
}
|
|
@@ -95510,6 +95816,32 @@ text = text.`,
|
|
|
95510
95816
|
}
|
|
95511
95817
|
return context;
|
|
95512
95818
|
}
|
|
95819
|
+
/** The result type of a call to a built-in function whose result type does not depend on its arguments,
|
|
95820
|
+
* undefined for anything else, e.g. abs( ) or xsdbool( ), or a method of the same name */
|
|
95821
|
+
builtinResultType(chain, scope) {
|
|
95822
|
+
var _a;
|
|
95823
|
+
const children = chain.getChildren();
|
|
95824
|
+
if (children.length !== 1 || !(children[0].get() instanceof Expressions.MethodCall)) {
|
|
95825
|
+
return undefined;
|
|
95826
|
+
}
|
|
95827
|
+
const name = (_a = children[0].findDirectExpression(Expressions.MethodName)) === null || _a === void 0 ? void 0 : _a.getFirstToken();
|
|
95828
|
+
if (name === undefined) {
|
|
95829
|
+
return undefined;
|
|
95830
|
+
}
|
|
95831
|
+
const isBuiltin = scope.getData().references.some(reference => reference.referenceType === _reference_1.ReferenceType.BuiltinMethodReference
|
|
95832
|
+
&& reference.position.getStart().equals(name.getStart()));
|
|
95833
|
+
if (isBuiltin === false) {
|
|
95834
|
+
return undefined;
|
|
95835
|
+
}
|
|
95836
|
+
const upper = name.getStr().toUpperCase();
|
|
95837
|
+
if (RedundantConversion.stringResult.has(upper)) {
|
|
95838
|
+
return basic_1.StringType.get();
|
|
95839
|
+
}
|
|
95840
|
+
else if (RedundantConversion.integerResult.has(upper)) {
|
|
95841
|
+
return basic_1.IntegerType.get();
|
|
95842
|
+
}
|
|
95843
|
+
return undefined;
|
|
95844
|
+
}
|
|
95513
95845
|
fieldChainType(fieldChain, scope) {
|
|
95514
95846
|
var _a;
|
|
95515
95847
|
const operand = (_a = scope.getData().references.find(reference => reference.referenceType === _reference_1.ReferenceType.DataReadReference
|
|
@@ -95574,6 +95906,17 @@ text = text.`,
|
|
|
95574
95906
|
}
|
|
95575
95907
|
}
|
|
95576
95908
|
exports.RedundantConversion = RedundantConversion;
|
|
95909
|
+
// built-in functions that always return a string, whatever their arguments
|
|
95910
|
+
RedundantConversion.stringResult = new Set([
|
|
95911
|
+
"BOOLC", "CONCAT_LINES_OF", "CONDENSE", "ESCAPE", "FROM_MIXED", "INSERT", "REPEAT", "REPLACE",
|
|
95912
|
+
"REVERSE", "SEGMENT", "SHIFT_LEFT", "SHIFT_RIGHT", "SUBSTRING", "SUBSTRING_AFTER", "SUBSTRING_BEFORE",
|
|
95913
|
+
"SUBSTRING_FROM", "SUBSTRING_TO", "TO_LOWER", "TO_MIXED", "TO_UPPER", "TRANSLATE"
|
|
95914
|
+
]);
|
|
95915
|
+
// built-in functions that always return an i
|
|
95916
|
+
RedundantConversion.integerResult = new Set([
|
|
95917
|
+
"CHARLEN", "COUNT", "COUNT_ANY_NOT_OF", "COUNT_ANY_OF", "DBMAXLEN", "DISTANCE", "FIND", "FIND_ANY_NOT_OF",
|
|
95918
|
+
"FIND_ANY_OF", "FIND_END", "LINES", "NUMOFCHAR", "STRLEN", "XSTRLEN"
|
|
95919
|
+
]);
|
|
95577
95920
|
//# sourceMappingURL=redundant_conversion.js.map
|
|
95578
95921
|
|
|
95579
95922
|
/***/ },
|
|
@@ -95914,7 +96257,9 @@ class RFCErrorHandling extends _abap_rule_1.ABAPRule {
|
|
|
95914
96257
|
title: "RFC error handling",
|
|
95915
96258
|
tags: [_irule_1.RuleTag.SingleFile],
|
|
95916
96259
|
shortDescription: `Checks that exceptions 'system_failure' and 'communication_failure' are handled in RFC calls`,
|
|
95917
|
-
extendedInformation: `
|
|
96260
|
+
extendedInformation: `RESOURCE_FAILURE is also required for asynchronous calls with DESTINATION IN GROUP.
|
|
96261
|
+
|
|
96262
|
+
https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/abenrfc_exception.html`,
|
|
95918
96263
|
badExample: `CALL FUNCTION 'ZRFC'
|
|
95919
96264
|
DESTINATION lv_rfc.`,
|
|
95920
96265
|
goodExample: `CALL FUNCTION 'ZRFC'
|
|
@@ -95922,12 +96267,12 @@ class RFCErrorHandling extends _abap_rule_1.ABAPRule {
|
|
|
95922
96267
|
EXCEPTIONS
|
|
95923
96268
|
system_failure = 1 MESSAGE msg
|
|
95924
96269
|
communication_failure = 2 MESSAGE msg
|
|
95925
|
-
|
|
95926
|
-
OTHERS = 4.`,
|
|
96270
|
+
OTHERS = 3.`,
|
|
95927
96271
|
};
|
|
95928
96272
|
}
|
|
95929
|
-
getMessage() {
|
|
95930
|
-
return "RFC error handling: At least one unhandled exception from SYSTEM_FAILURE, COMMUNICATION_FAILURE
|
|
96273
|
+
getMessage(requireResourceFailure) {
|
|
96274
|
+
return "RFC error handling: At least one unhandled exception from SYSTEM_FAILURE, COMMUNICATION_FAILURE"
|
|
96275
|
+
+ (requireResourceFailure ? ", RESOURCE_FAILURE" : "");
|
|
95931
96276
|
}
|
|
95932
96277
|
getConfig() {
|
|
95933
96278
|
return this.conf;
|
|
@@ -95942,12 +96287,15 @@ class RFCErrorHandling extends _abap_rule_1.ABAPRule {
|
|
|
95942
96287
|
if (!(stat.get() instanceof Statements.CallFunction)) {
|
|
95943
96288
|
continue;
|
|
95944
96289
|
}
|
|
95945
|
-
|
|
96290
|
+
const destination = stat.findFirstExpression(Expressions.Destination);
|
|
96291
|
+
if (destination === undefined) {
|
|
95946
96292
|
continue;
|
|
95947
96293
|
}
|
|
96294
|
+
const requireResourceFailure = stat.findDirectTokenByText("STARTING") !== undefined
|
|
96295
|
+
&& destination.findDirectTokenByText("GROUP") !== undefined;
|
|
95948
96296
|
const list = stat.findFirstExpression(Expressions.ParameterListExceptions);
|
|
95949
96297
|
if (list === undefined) {
|
|
95950
|
-
const issue = issue_1.Issue.atToken(file, token, this.getMessage(), this.getMetadata().key, this.conf.severity);
|
|
96298
|
+
const issue = issue_1.Issue.atToken(file, token, this.getMessage(requireResourceFailure), this.getMetadata().key, this.conf.severity);
|
|
95951
96299
|
output.push(issue);
|
|
95952
96300
|
continue;
|
|
95953
96301
|
}
|
|
@@ -95958,8 +96306,8 @@ class RFCErrorHandling extends _abap_rule_1.ABAPRule {
|
|
|
95958
96306
|
}
|
|
95959
96307
|
if (names.indexOf("SYSTEM_FAILURE") < 0
|
|
95960
96308
|
|| names.indexOf("COMMUNICATION_FAILURE") < 0
|
|
95961
|
-
|| names.indexOf("RESOURCE_FAILURE") < 0) {
|
|
95962
|
-
const issue = issue_1.Issue.atToken(file, token, this.getMessage(), this.getMetadata().key, this.conf.severity);
|
|
96309
|
+
|| (requireResourceFailure && names.indexOf("RESOURCE_FAILURE") < 0)) {
|
|
96310
|
+
const issue = issue_1.Issue.atToken(file, token, this.getMessage(requireResourceFailure), this.getMetadata().key, this.conf.severity);
|
|
95963
96311
|
output.push(issue);
|
|
95964
96312
|
continue;
|
|
95965
96313
|
}
|
|
@@ -102774,7 +103122,7 @@ class XMLConsistency {
|
|
|
102774
103122
|
}
|
|
102775
103123
|
runTable(obj, file) {
|
|
102776
103124
|
var _a, _b, _c, _d;
|
|
102777
|
-
var _e;
|
|
103125
|
+
var _e, _f;
|
|
102778
103126
|
const issues = [];
|
|
102779
103127
|
for (const field of (_e = obj.getFields()) !== null && _e !== void 0 ? _e : []) {
|
|
102780
103128
|
if (field.DATATYPE === "QUAN" && (!((_a = field.REFTABLE) === null || _a === void 0 ? void 0 : _a.trim()) || !((_b = field.REFFIELD) === null || _b === void 0 ? void 0 : _b.trim()))) {
|
|
@@ -102783,6 +103131,14 @@ class XMLConsistency {
|
|
|
102783
103131
|
}
|
|
102784
103132
|
}
|
|
102785
103133
|
if (obj.getTableCategory() === Objects.TableCategory.Transparent) {
|
|
103134
|
+
// Confirmed reserved database field names, see issue #4331, DAY and HOUR reported by activation.
|
|
103135
|
+
// TRESE also contains names such as TEXT and LENGTH which are allowed here.
|
|
103136
|
+
const reservedFieldNames = ["ZONE", "HANDLER", "SECTION", "PARAMETER", "DAY", "HOUR"];
|
|
103137
|
+
for (const field of (_f = obj.getFields()) !== null && _f !== void 0 ? _f : []) {
|
|
103138
|
+
if (reservedFieldNames.includes(field.FIELDNAME.toUpperCase())) {
|
|
103139
|
+
issues.push(issue_1.Issue.atRow(file, 1, `Table field name "${field.FIELDNAME}" is reserved`, this.getMetadata().key, this.conf.severity));
|
|
103140
|
+
}
|
|
103141
|
+
}
|
|
102786
103142
|
if (!((_c = obj.getDeliveryClass()) === null || _c === void 0 ? void 0 : _c.trim())) {
|
|
102787
103143
|
const message = `Transparent table must have delivery class(CONTFLAG in DD02V) set`;
|
|
102788
103144
|
issues.push(issue_1.Issue.atRow(file, 1, message, this.getMetadata().key, this.conf.transparentTableSeverity));
|
|
@@ -104393,6 +104749,12 @@ class Chunk {
|
|
|
104393
104749
|
original: m.original,
|
|
104394
104750
|
generated: { line: m.generated.line + offset, column: m.generated.column },
|
|
104395
104751
|
}));
|
|
104752
|
+
for (const source of new Set(this.mappings.map(m => m.source))) {
|
|
104753
|
+
const contents = options?.sourceContents?.[source];
|
|
104754
|
+
if (contents !== undefined) {
|
|
104755
|
+
sourceMapGenerator.setSourceContent(sourcePaths[source] ?? source, contents);
|
|
104756
|
+
}
|
|
104757
|
+
}
|
|
104396
104758
|
const json = sourceMapGenerator.toJSON();
|
|
104397
104759
|
json.file = generatedFilename;
|
|
104398
104760
|
json.sourceRoot = "";
|
|
@@ -104404,6 +104766,231 @@ exports.Chunk = Chunk;
|
|
|
104404
104766
|
|
|
104405
104767
|
/***/ },
|
|
104406
104768
|
|
|
104769
|
+
/***/ "./node_modules/@abaplint/transpiler/build/src/db/cds_database_view.js"
|
|
104770
|
+
/*!*****************************************************************************!*\
|
|
104771
|
+
!*** ./node_modules/@abaplint/transpiler/build/src/db/cds_database_view.js ***!
|
|
104772
|
+
\*****************************************************************************/
|
|
104773
|
+
(__unused_webpack_module, exports, __webpack_require__) {
|
|
104774
|
+
|
|
104775
|
+
"use strict";
|
|
104776
|
+
|
|
104777
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
104778
|
+
if (k2 === undefined) k2 = k;
|
|
104779
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
104780
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
104781
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
104782
|
+
}
|
|
104783
|
+
Object.defineProperty(o, k2, desc);
|
|
104784
|
+
}) : (function(o, m, k, k2) {
|
|
104785
|
+
if (k2 === undefined) k2 = k;
|
|
104786
|
+
o[k2] = m[k];
|
|
104787
|
+
}));
|
|
104788
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
104789
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
104790
|
+
}) : function(o, v) {
|
|
104791
|
+
o["default"] = v;
|
|
104792
|
+
});
|
|
104793
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
104794
|
+
var ownKeys = function(o) {
|
|
104795
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
104796
|
+
var ar = [];
|
|
104797
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
104798
|
+
return ar;
|
|
104799
|
+
};
|
|
104800
|
+
return ownKeys(o);
|
|
104801
|
+
};
|
|
104802
|
+
return function (mod) {
|
|
104803
|
+
if (mod && mod.__esModule) return mod;
|
|
104804
|
+
var result = {};
|
|
104805
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
104806
|
+
__setModuleDefault(result, mod);
|
|
104807
|
+
return result;
|
|
104808
|
+
};
|
|
104809
|
+
})();
|
|
104810
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
104811
|
+
exports.CDSDatabaseView = void 0;
|
|
104812
|
+
const abaplint = __importStar(__webpack_require__(/*! @abaplint/core */ "./node_modules/@abaplint/core/build/src/index.js"));
|
|
104813
|
+
const cds = abaplint.ExpressionsCDS;
|
|
104814
|
+
/** SQL for the supported relational subset of CDS. Never discard unknown syntax. */
|
|
104815
|
+
class CDSDatabaseView {
|
|
104816
|
+
reg;
|
|
104817
|
+
viewName = "";
|
|
104818
|
+
sources = [];
|
|
104819
|
+
constructor(reg) {
|
|
104820
|
+
this.reg = reg;
|
|
104821
|
+
}
|
|
104822
|
+
build(obj) {
|
|
104823
|
+
this.viewName = obj.getName();
|
|
104824
|
+
const tree = new abaplint.CDSParser().parse(obj.findSourceFile());
|
|
104825
|
+
if (tree === undefined) {
|
|
104826
|
+
return this.unsupported("could not parse CDS definition");
|
|
104827
|
+
}
|
|
104828
|
+
else if (!(tree.get() instanceof cds.CDSDefineView)) {
|
|
104829
|
+
return undefined; // Abstract/custom entities have no database view.
|
|
104830
|
+
}
|
|
104831
|
+
const name = tree.findDirectExpression(cds.CDSName);
|
|
104832
|
+
const select = tree.findDirectExpression(cds.CDSSelect);
|
|
104833
|
+
if (name === undefined || select === undefined) {
|
|
104834
|
+
return this.unsupported("expected a SELECT view");
|
|
104835
|
+
}
|
|
104836
|
+
this.viewName = this.name(name);
|
|
104837
|
+
for (const child of tree.getChildren()) {
|
|
104838
|
+
if (child === name || child === select || child.get() instanceof cds.CDSAnnotation) {
|
|
104839
|
+
continue;
|
|
104840
|
+
}
|
|
104841
|
+
this.keyword(child, ["DEFINE", "ROOT", "VIEW", "ENTITY", "AS", ";"]);
|
|
104842
|
+
}
|
|
104843
|
+
const source = select.findDirectExpression(cds.CDSSource);
|
|
104844
|
+
if (source === undefined) {
|
|
104845
|
+
return this.unsupported("missing source");
|
|
104846
|
+
}
|
|
104847
|
+
const from = [this.source(source)];
|
|
104848
|
+
for (const join of select.findDirectExpressions(cds.CDSJoin)) {
|
|
104849
|
+
from.push(this.join(join));
|
|
104850
|
+
}
|
|
104851
|
+
const elements = select.findDirectExpressions(cds.CDSElement);
|
|
104852
|
+
if (elements.length === 0) {
|
|
104853
|
+
return this.unsupported("expected explicit projected fields");
|
|
104854
|
+
}
|
|
104855
|
+
const columns = elements.map(e => this.element(e)).join(", ");
|
|
104856
|
+
let where = "";
|
|
104857
|
+
for (const child of select.getChildren()) {
|
|
104858
|
+
if (child === source || child.get() instanceof cds.CDSJoin || child.get() instanceof cds.CDSElement) {
|
|
104859
|
+
continue;
|
|
104860
|
+
}
|
|
104861
|
+
else if (child.get() instanceof cds.CDSWhere) {
|
|
104862
|
+
where = " " + this.expression(child);
|
|
104863
|
+
}
|
|
104864
|
+
else {
|
|
104865
|
+
this.keyword(child, ["SELECT", "DISTINCT", "FROM", "{", "}", ","]);
|
|
104866
|
+
}
|
|
104867
|
+
}
|
|
104868
|
+
const distinct = select.findDirectTokenByText("DISTINCT") ? "DISTINCT " : "";
|
|
104869
|
+
return `CREATE VIEW ${this.quote(this.viewName)} AS SELECT ${distinct}${columns} FROM ${from.join(" ")}${where};`;
|
|
104870
|
+
}
|
|
104871
|
+
source(node) {
|
|
104872
|
+
const nameNode = node.findDirectExpression(cds.CDSPrefixedName);
|
|
104873
|
+
if (nameNode === undefined) {
|
|
104874
|
+
return this.unsupported("expected a table source");
|
|
104875
|
+
}
|
|
104876
|
+
const name = this.name(nameNode);
|
|
104877
|
+
if (this.reg.getObject("TABL", name)?.getType() !== "TABL") {
|
|
104878
|
+
return this.unsupported(`source ${name} does not resolve to a TABL`);
|
|
104879
|
+
}
|
|
104880
|
+
const as = node.findDirectExpression(cds.CDSAs);
|
|
104881
|
+
const alias = as?.findDirectExpression(cds.CDSName) || node.findDirectExpression(cds.CDSName);
|
|
104882
|
+
for (const child of node.getChildren()) {
|
|
104883
|
+
if (child !== nameNode && child !== as && child !== alias) {
|
|
104884
|
+
return this.unsupported("source parameters, filters or nested joins");
|
|
104885
|
+
}
|
|
104886
|
+
}
|
|
104887
|
+
this.sources.push(alias ? this.name(alias) : name);
|
|
104888
|
+
return this.quote(name) + (alias ? " AS " + this.quote(this.name(alias)) : "");
|
|
104889
|
+
}
|
|
104890
|
+
join(node) {
|
|
104891
|
+
const sources = node.findDirectExpressions(cds.CDSSource);
|
|
104892
|
+
const conditions = node.findDirectExpressions(cds.CDSCondition);
|
|
104893
|
+
const words = node.getDirectTokens().map(t => t.getStr().toUpperCase()).join(" ");
|
|
104894
|
+
const match = /^(?:(INNER|LEFT OUTER|RIGHT OUTER|CROSS) )?JOIN(?: ON)?$/.exec(words);
|
|
104895
|
+
if (sources.length !== 1 || match === null) {
|
|
104896
|
+
return this.unsupported("join shape: " + node.concatTokens());
|
|
104897
|
+
}
|
|
104898
|
+
const kind = match[1] || "INNER";
|
|
104899
|
+
if (conditions.length !== (kind === "CROSS" ? 0 : 1)) {
|
|
104900
|
+
return this.unsupported("join requires an ON condition (except CROSS JOIN)");
|
|
104901
|
+
}
|
|
104902
|
+
const source = this.source(sources[0]);
|
|
104903
|
+
return kind + " JOIN " + source + (conditions.length ? " ON " + this.expression(conditions[0]) : "");
|
|
104904
|
+
}
|
|
104905
|
+
element(node) {
|
|
104906
|
+
const field = node.findDirectExpression(cds.CDSPrefixedName);
|
|
104907
|
+
const as = node.findDirectExpression(cds.CDSAs);
|
|
104908
|
+
for (const child of node.getChildren()) {
|
|
104909
|
+
if (child === field || child === as || child.get() instanceof cds.CDSAnnotation) {
|
|
104910
|
+
continue;
|
|
104911
|
+
}
|
|
104912
|
+
this.keyword(child, ["KEY"]);
|
|
104913
|
+
}
|
|
104914
|
+
if (field === undefined) {
|
|
104915
|
+
return this.unsupported("expected a projected source field");
|
|
104916
|
+
}
|
|
104917
|
+
const parts = this.fieldParts(field);
|
|
104918
|
+
const alias = as?.findDirectExpression(cds.CDSName);
|
|
104919
|
+
return this.field(field) + " AS " + this.quote(alias ? this.name(alias) : parts[parts.length - 1]);
|
|
104920
|
+
}
|
|
104921
|
+
expression(node) {
|
|
104922
|
+
if (node instanceof abaplint.Nodes.TokenNode) {
|
|
104923
|
+
return this.keyword(node, ["WHERE", "AND", "OR", "NOT", "IS", "NULL", "LIKE", "ESCAPE", "BETWEEN",
|
|
104924
|
+
"=", "!", "<", ">", "(", ")"]);
|
|
104925
|
+
}
|
|
104926
|
+
else if (node.get() instanceof cds.CDSPrefixedName) {
|
|
104927
|
+
if (node.getTokens().map(t => t.getStr()).join("").toLowerCase() === "$session.system_language") {
|
|
104928
|
+
return "'E'";
|
|
104929
|
+
}
|
|
104930
|
+
return this.field(node);
|
|
104931
|
+
}
|
|
104932
|
+
else if (node.get() instanceof cds.CDSString || node.get() instanceof cds.CDSInteger) {
|
|
104933
|
+
return node.getTokens().map(t => t.getStr()).join("");
|
|
104934
|
+
}
|
|
104935
|
+
else if (node.get() instanceof cds.CDSCondition || node.get() instanceof cds.CDSWhere) {
|
|
104936
|
+
const parts = [];
|
|
104937
|
+
for (const child of node.getChildren()) {
|
|
104938
|
+
const part = this.expression(child);
|
|
104939
|
+
if (["<", ">", "!"].includes(parts[parts.length - 1]) && ["=", ">"].includes(part)) {
|
|
104940
|
+
parts[parts.length - 1] += part;
|
|
104941
|
+
}
|
|
104942
|
+
else {
|
|
104943
|
+
parts.push(part);
|
|
104944
|
+
}
|
|
104945
|
+
}
|
|
104946
|
+
return parts.join(" ");
|
|
104947
|
+
}
|
|
104948
|
+
return this.unsupported(node.concatTokens());
|
|
104949
|
+
}
|
|
104950
|
+
field(node) {
|
|
104951
|
+
const parts = this.fieldParts(node);
|
|
104952
|
+
if (parts.length === 1 && this.sources.length === 1) {
|
|
104953
|
+
parts.unshift(this.sources[0]);
|
|
104954
|
+
}
|
|
104955
|
+
else if (parts.length === 2 && !this.sources.includes(parts[0])) {
|
|
104956
|
+
return this.unsupported("unknown source qualifier " + parts[0]);
|
|
104957
|
+
}
|
|
104958
|
+
return parts.map(p => this.quote(p)).join(".");
|
|
104959
|
+
}
|
|
104960
|
+
fieldParts(node) {
|
|
104961
|
+
const text = node.getTokens().map(t => t.getStr()).join("").toLowerCase();
|
|
104962
|
+
const parts = text.split(".");
|
|
104963
|
+
if (parts.length > 2 || parts.some(p => !/^(\/\w+\/)?\w+$/.test(p))) {
|
|
104964
|
+
return this.unsupported("field path " + text);
|
|
104965
|
+
}
|
|
104966
|
+
return parts;
|
|
104967
|
+
}
|
|
104968
|
+
name(node) {
|
|
104969
|
+
const name = node.getTokens().map(t => t.getStr()).join("").toLowerCase();
|
|
104970
|
+
if (!/^(\/\w+\/)?\w+$/.test(name)) {
|
|
104971
|
+
return this.unsupported("identifier " + name);
|
|
104972
|
+
}
|
|
104973
|
+
return name;
|
|
104974
|
+
}
|
|
104975
|
+
keyword(node, allowed) {
|
|
104976
|
+
const text = node.concatTokens().toUpperCase();
|
|
104977
|
+
if (!(node instanceof abaplint.Nodes.TokenNode) || !allowed.includes(text)) {
|
|
104978
|
+
return this.unsupported(node.concatTokens());
|
|
104979
|
+
}
|
|
104980
|
+
return text;
|
|
104981
|
+
}
|
|
104982
|
+
quote(name) {
|
|
104983
|
+
return '"' + name.toLowerCase().replace(/"/g, '""') + '"';
|
|
104984
|
+
}
|
|
104985
|
+
unsupported(detail) {
|
|
104986
|
+
throw new Error(`CDS view ${this.viewName}: unsupported database definition: ${detail}`);
|
|
104987
|
+
}
|
|
104988
|
+
}
|
|
104989
|
+
exports.CDSDatabaseView = CDSDatabaseView;
|
|
104990
|
+
//# sourceMappingURL=cds_database_view.js.map
|
|
104991
|
+
|
|
104992
|
+
/***/ },
|
|
104993
|
+
|
|
104407
104994
|
/***/ "./node_modules/@abaplint/transpiler/build/src/db/index.js"
|
|
104408
104995
|
/*!*****************************************************************!*\
|
|
104409
104996
|
!*** ./node_modules/@abaplint/transpiler/build/src/db/index.js ***!
|
|
@@ -104452,6 +105039,7 @@ const sqlite_database_schema_1 = __webpack_require__(/*! ./schema_generation/sql
|
|
|
104452
105039
|
const pg_database_schema_1 = __webpack_require__(/*! ./schema_generation/pg_database_schema */ "./node_modules/@abaplint/transpiler/build/src/db/schema_generation/pg_database_schema.js");
|
|
104453
105040
|
const snowflake_database_schema_1 = __webpack_require__(/*! ./schema_generation/snowflake_database_schema */ "./node_modules/@abaplint/transpiler/build/src/db/schema_generation/snowflake_database_schema.js");
|
|
104454
105041
|
const populate_tables_1 = __webpack_require__(/*! ./populate_tables */ "./node_modules/@abaplint/transpiler/build/src/db/populate_tables.js");
|
|
105042
|
+
const cds_database_view_1 = __webpack_require__(/*! ./cds_database_view */ "./node_modules/@abaplint/transpiler/build/src/db/cds_database_view.js");
|
|
104455
105043
|
/////////////////////////
|
|
104456
105044
|
// NOTES
|
|
104457
105045
|
/////////////////////////
|
|
@@ -104463,9 +105051,11 @@ class DatabaseSetup {
|
|
|
104463
105051
|
this.reg = reg;
|
|
104464
105052
|
}
|
|
104465
105053
|
run(options) {
|
|
105054
|
+
// CDS views are dialect independent SQL, added after the tables and views they select from
|
|
105055
|
+
const cdsViews = this.buildCDSViews();
|
|
104466
105056
|
return {
|
|
104467
105057
|
schemas: {
|
|
104468
|
-
sqlite: this.driver(new sqlite_database_schema_1.SQLiteDatabaseSchema(this.reg)),
|
|
105058
|
+
sqlite: [...this.driver(new sqlite_database_schema_1.SQLiteDatabaseSchema(this.reg)), ...cdsViews],
|
|
104469
105059
|
// HANA takes the PG schema unchanged -- measured against HANA Express
|
|
104470
105060
|
// on a tree of 77 tables. The one thing it needs is that identifiers
|
|
104471
105061
|
// reach it quoted in UPPER case, and that is not a dialect of DDL: the
|
|
@@ -104474,13 +105064,25 @@ class DatabaseSetup {
|
|
|
104474
105064
|
// here. (Unquoted would nearly work and then meet a column called
|
|
104475
105065
|
// `cross`, which is one of HANA's reserved words.)
|
|
104476
105066
|
hdb: this.driver(new pg_database_schema_1.PGDatabaseSchema(this.reg)),
|
|
104477
|
-
pg: this.driver(new pg_database_schema_1.PGDatabaseSchema(this.reg)),
|
|
104478
|
-
snowflake: this.driver(new snowflake_database_schema_1.SnowflakeDatabaseSchema(this.reg)),
|
|
105067
|
+
pg: [...this.driver(new pg_database_schema_1.PGDatabaseSchema(this.reg)), ...cdsViews],
|
|
105068
|
+
snowflake: [...this.driver(new snowflake_database_schema_1.SnowflakeDatabaseSchema(this.reg)), ...cdsViews],
|
|
104479
105069
|
},
|
|
104480
105070
|
insert: this.buildInsert(options),
|
|
104481
105071
|
};
|
|
104482
105072
|
}
|
|
104483
105073
|
////////////////////
|
|
105074
|
+
buildCDSViews() {
|
|
105075
|
+
const views = [];
|
|
105076
|
+
for (const obj of this.reg.getObjects()) {
|
|
105077
|
+
if (obj instanceof abaplint.Objects.DataDefinition) {
|
|
105078
|
+
const view = new cds_database_view_1.CDSDatabaseView(this.reg).build(obj);
|
|
105079
|
+
if (view !== undefined) {
|
|
105080
|
+
views.push(view);
|
|
105081
|
+
}
|
|
105082
|
+
}
|
|
105083
|
+
}
|
|
105084
|
+
return views;
|
|
105085
|
+
}
|
|
104484
105086
|
driver(schemaGenerator) {
|
|
104485
105087
|
const statements = [];
|
|
104486
105088
|
// CREATE TABLEs
|
|
@@ -105631,12 +106233,12 @@ class CompareTranspiler {
|
|
|
105631
106233
|
const field = concat.replace(" IS NOT REQUESTED", "").toLowerCase();
|
|
105632
106234
|
return new chunk_1.Chunk().appendString(pre + "INPUT && INPUT." + field + " === undefined && INPUT.importing?." + field + " === undefined");
|
|
105633
106235
|
}
|
|
105634
|
-
if (concat.includes(" IS INSTANCE OF ")) {
|
|
105635
|
-
const notted = concat.startsWith("NOT ")
|
|
106236
|
+
if (concat.includes(" IS INSTANCE OF ") || concat.includes(" IS NOT INSTANCE OF ")) {
|
|
106237
|
+
const notted = concat.startsWith("NOT ") !== concat.includes(" IS NOT INSTANCE OF ");
|
|
105636
106238
|
const falsed = notted ? " === false" : "";
|
|
105637
106239
|
const expr = node.findDirectExpression(core_1.Expressions.ClassName);
|
|
105638
106240
|
const cname = expr?.concatTokens();
|
|
105639
|
-
const lookup = traversal.lookupClassOrInterface(cname, expr?.getFirstToken());
|
|
106241
|
+
const lookup = cname?.toUpperCase() === "OBJECT" ? '"OBJECT"' : traversal.lookupClassOrInterface(cname, expr?.getFirstToken());
|
|
105640
106242
|
return new chunk_1.Chunk().appendString("abap.compare.instance_of(").appendChunk(s0).appendString(`, ${lookup})` + falsed);
|
|
105641
106243
|
}
|
|
105642
106244
|
}
|
|
@@ -111286,10 +111888,12 @@ const traversal_1 = __webpack_require__(/*! ../traversal */ "./node_modules/@aba
|
|
|
111286
111888
|
const requires_1 = __webpack_require__(/*! ../requires */ "./node_modules/@abaplint/transpiler/build/src/requires.js");
|
|
111287
111889
|
const rearranger_1 = __webpack_require__(/*! ../rearranger */ "./node_modules/@abaplint/transpiler/build/src/rearranger.js");
|
|
111288
111890
|
const chunk_1 = __webpack_require__(/*! ../chunk */ "./node_modules/@abaplint/transpiler/build/src/chunk.js");
|
|
111289
|
-
const
|
|
111891
|
+
const output_layout_1 = __webpack_require__(/*! ../output_layout */ "./node_modules/@abaplint/transpiler/build/src/output_layout.js");
|
|
111290
111892
|
class HandleABAP {
|
|
111893
|
+
layout;
|
|
111291
111894
|
options;
|
|
111292
|
-
constructor(options) {
|
|
111895
|
+
constructor(options, layout = new output_layout_1.OutputLayout()) {
|
|
111896
|
+
this.layout = layout;
|
|
111293
111897
|
this.options = options;
|
|
111294
111898
|
}
|
|
111295
111899
|
runObject(obj, reg) {
|
|
@@ -111390,11 +111994,12 @@ class HandleABAP {
|
|
|
111390
111994
|
if (filename === output.filename) {
|
|
111391
111995
|
continue;
|
|
111392
111996
|
}
|
|
111997
|
+
const specifier = (0, output_layout_1.importPath)(this.layout.file(output.object, output.filename), this.layout.sourceModule(r.filename));
|
|
111393
111998
|
if (name) {
|
|
111394
|
-
contents.appendString("const {" + traversal_1.Traversal.escapeNamespace(name) + "} = await import(\"
|
|
111999
|
+
contents.appendString("const {" + traversal_1.Traversal.escapeNamespace(name) + "} = await import(\"" + specifier + "\");\n");
|
|
111395
112000
|
}
|
|
111396
112001
|
else {
|
|
111397
|
-
contents.appendString("await import(\"
|
|
112002
|
+
contents.appendString("await import(\"" + specifier + "\");\n");
|
|
111398
112003
|
}
|
|
111399
112004
|
}
|
|
111400
112005
|
contents.appendChunk(output.chunk);
|
|
@@ -111722,7 +112327,13 @@ exports.HandleOA2P = HandleOA2P;
|
|
|
111722
112327
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
111723
112328
|
exports.HandleSMIM = void 0;
|
|
111724
112329
|
const chunk_1 = __webpack_require__(/*! ../chunk */ "./node_modules/@abaplint/transpiler/build/src/chunk.js");
|
|
112330
|
+
const output_layout_1 = __webpack_require__(/*! ../output_layout */ "./node_modules/@abaplint/transpiler/build/src/output_layout.js");
|
|
111725
112331
|
class HandleSMIM {
|
|
112332
|
+
layout;
|
|
112333
|
+
constructor(layout = new output_layout_1.OutputLayout()) {
|
|
112334
|
+
this.layout = layout;
|
|
112335
|
+
// Asset paths are relative to the output root.
|
|
112336
|
+
}
|
|
111726
112337
|
runObject(obj, _reg) {
|
|
111727
112338
|
const filename = obj.getXMLFile()?.getFilename().replace(".xml", ".mjs").toLowerCase();
|
|
111728
112339
|
if (filename === undefined) {
|
|
@@ -111730,9 +112341,10 @@ class HandleSMIM {
|
|
|
111730
112341
|
}
|
|
111731
112342
|
obj.parse();
|
|
111732
112343
|
const dataFile = obj.getDataFile();
|
|
112344
|
+
const dataFilename = dataFile ? this.layout.file({ name: obj.getName(), type: obj.getType() }, dataFile.getFilename()) : undefined;
|
|
111733
112345
|
const chunk = new chunk_1.Chunk().appendString(`abap.SMIM["${obj.getName().toUpperCase()}"] = {
|
|
111734
112346
|
"objectType": "SMIM",
|
|
111735
|
-
"filename": ${JSON.stringify(
|
|
112347
|
+
"filename": ${JSON.stringify(dataFilename)},
|
|
111736
112348
|
"url": ${JSON.stringify(obj.getURL())},
|
|
111737
112349
|
"class": ${JSON.stringify(obj.getClass())},
|
|
111738
112350
|
};`);
|
|
@@ -112005,8 +112617,14 @@ exports.HandleView = HandleView;
|
|
|
112005
112617
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
112006
112618
|
exports.HandleW3MI = void 0;
|
|
112007
112619
|
const chunk_1 = __webpack_require__(/*! ../chunk */ "./node_modules/@abaplint/transpiler/build/src/chunk.js");
|
|
112620
|
+
const output_layout_1 = __webpack_require__(/*! ../output_layout */ "./node_modules/@abaplint/transpiler/build/src/output_layout.js");
|
|
112008
112621
|
const w3mi_name_1 = __webpack_require__(/*! ../w3mi_name */ "./node_modules/@abaplint/transpiler/build/src/w3mi_name.js");
|
|
112009
112622
|
class HandleW3MI {
|
|
112623
|
+
layout;
|
|
112624
|
+
constructor(layout = new output_layout_1.OutputLayout()) {
|
|
112625
|
+
this.layout = layout;
|
|
112626
|
+
// Asset paths are relative to the output root.
|
|
112627
|
+
}
|
|
112010
112628
|
runObject(obj, _reg) {
|
|
112011
112629
|
const filename = obj.getXMLFile()?.getFilename().replace(".xml", ".mjs").toLowerCase();
|
|
112012
112630
|
if (filename === undefined) {
|
|
@@ -112014,9 +112632,10 @@ class HandleW3MI {
|
|
|
112014
112632
|
}
|
|
112015
112633
|
obj.parse();
|
|
112016
112634
|
const dataFile = obj.getDataFile();
|
|
112635
|
+
const dataFilename = dataFile ? this.layout.file({ name: obj.getName(), type: obj.getType() }, dataFile.getFilename()) : undefined;
|
|
112017
112636
|
const chunk = new chunk_1.Chunk().appendString(`abap.W3MI["${(0, w3mi_name_1.w3miObjectName)(obj)}"] = {
|
|
112018
112637
|
"objectType": "W3MI",
|
|
112019
|
-
"filename": ${JSON.stringify(
|
|
112638
|
+
"filename": ${JSON.stringify(dataFilename)},
|
|
112020
112639
|
};`);
|
|
112021
112640
|
const output = {
|
|
112022
112641
|
object: {
|
|
@@ -112092,7 +112711,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
112092
112711
|
};
|
|
112093
112712
|
})();
|
|
112094
112713
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
112095
|
-
exports.Transpiler = exports.Chunk = exports.UnknownTypesEnum = exports.config = void 0;
|
|
112714
|
+
exports.Transpiler = exports.Chunk = exports.UnknownTypesEnum = exports.config = exports.importPath = exports.OutputLayout = void 0;
|
|
112096
112715
|
const abaplint = __importStar(__webpack_require__(/*! @abaplint/core */ "./node_modules/@abaplint/core/build/src/index.js"));
|
|
112097
112716
|
const validation_1 = __webpack_require__(/*! ./validation */ "./node_modules/@abaplint/transpiler/build/src/validation.js");
|
|
112098
112717
|
Object.defineProperty(exports, "config", ({ enumerable: true, get: function () { return validation_1.config; } }));
|
|
@@ -112116,12 +112735,14 @@ const handle_msag_1 = __webpack_require__(/*! ./handlers/handle_msag */ "./node_
|
|
|
112116
112735
|
const handle_oa2p_1 = __webpack_require__(/*! ./handlers/handle_oa2p */ "./node_modules/@abaplint/transpiler/build/src/handlers/handle_oa2p.js");
|
|
112117
112736
|
const handle_fugr_1 = __webpack_require__(/*! ./handlers/handle_fugr */ "./node_modules/@abaplint/transpiler/build/src/handlers/handle_fugr.js");
|
|
112118
112737
|
const initialization_1 = __webpack_require__(/*! ./initialization */ "./node_modules/@abaplint/transpiler/build/src/initialization.js");
|
|
112738
|
+
const output_layout_1 = __webpack_require__(/*! ./output_layout */ "./node_modules/@abaplint/transpiler/build/src/output_layout.js");
|
|
112739
|
+
var output_layout_2 = __webpack_require__(/*! ./output_layout */ "./node_modules/@abaplint/transpiler/build/src/output_layout.js");
|
|
112740
|
+
Object.defineProperty(exports, "OutputLayout", ({ enumerable: true, get: function () { return output_layout_2.OutputLayout; } }));
|
|
112741
|
+
Object.defineProperty(exports, "importPath", ({ enumerable: true, get: function () { return output_layout_2.importPath; } }));
|
|
112119
112742
|
class Transpiler {
|
|
112120
112743
|
options;
|
|
112121
|
-
|
|
112122
|
-
constructor(options, plugin) {
|
|
112744
|
+
constructor(options) {
|
|
112123
112745
|
this.options = options;
|
|
112124
|
-
this.plugin = plugin;
|
|
112125
112746
|
if (this.options === undefined) {
|
|
112126
112747
|
this.options = {};
|
|
112127
112748
|
}
|
|
@@ -112135,23 +112756,22 @@ class Transpiler {
|
|
|
112135
112756
|
const reg = new abaplint.Registry().addFiles(memory);
|
|
112136
112757
|
return this.run(reg);
|
|
112137
112758
|
}
|
|
112138
|
-
async run(reg, progress) {
|
|
112759
|
+
async run(reg, progress, folders) {
|
|
112139
112760
|
// Validation installs the transpiler configuration and findIssues() parses
|
|
112140
112761
|
// dirty registries. Parsing before that would be wasted because setConfig()
|
|
112141
112762
|
// marks every registry object dirty again.
|
|
112142
112763
|
this.validate(reg);
|
|
112764
|
+
const layout = new output_layout_1.OutputLayout(reg, folders);
|
|
112143
112765
|
const dbSetup = new db_1.DatabaseSetup(reg).run(this.options);
|
|
112144
|
-
this.plugin?.amendDatabaseSetup?.(dbSetup, reg, this.options || {});
|
|
112145
112766
|
const output = {
|
|
112146
112767
|
objects: [],
|
|
112147
|
-
unitTestScript: new unit_test_1.UnitTest().unitTestScript(reg, this.options?.skip),
|
|
112148
|
-
unitTestScriptOpen: new unit_test_1.UnitTest().unitTestScriptOpen(reg, this.options?.skip),
|
|
112768
|
+
unitTestScript: new unit_test_1.UnitTest(layout).unitTestScript(reg, this.options?.skip),
|
|
112769
|
+
unitTestScriptOpen: new unit_test_1.UnitTest(layout).unitTestScriptOpen(reg, this.options?.skip),
|
|
112149
112770
|
initializationScript: "",
|
|
112150
112771
|
initializationScript2: "",
|
|
112151
112772
|
databaseSetup: dbSetup,
|
|
112152
112773
|
reg: reg,
|
|
112153
112774
|
};
|
|
112154
|
-
const pluginOutputs = [];
|
|
112155
112775
|
progress?.set(reg.getObjectCount().total, "Building");
|
|
112156
112776
|
for (const obj of reg.getObjects()) {
|
|
112157
112777
|
await progress?.tick("Building, " + obj.getName());
|
|
@@ -112168,7 +112788,7 @@ class Transpiler {
|
|
|
112168
112788
|
output.objects.push(...new handle_fugr_1.HandleFUGR(this.options).runObject(obj, reg));
|
|
112169
112789
|
}
|
|
112170
112790
|
else if (obj instanceof abaplint.ABAPObject) {
|
|
112171
|
-
output.objects.push(...new handle_abap_1.HandleABAP(this.options).runObject(obj, reg));
|
|
112791
|
+
output.objects.push(...new handle_abap_1.HandleABAP(this.options, layout).runObject(obj, reg));
|
|
112172
112792
|
}
|
|
112173
112793
|
else if (obj instanceof abaplint.Objects.Oauth2Profile) {
|
|
112174
112794
|
output.objects.push(...new handle_oa2p_1.HandleOA2P().runObject(obj, reg));
|
|
@@ -112189,30 +112809,25 @@ class Transpiler {
|
|
|
112189
112809
|
output.objects.push(...new handle_table_type_1.HandleTableType().runObject(obj, reg));
|
|
112190
112810
|
}
|
|
112191
112811
|
else if (obj instanceof abaplint.Objects.MIMEObject) {
|
|
112192
|
-
output.objects.push(...new handle_smim_1.HandleSMIM().runObject(obj, reg));
|
|
112812
|
+
output.objects.push(...new handle_smim_1.HandleSMIM(layout).runObject(obj, reg));
|
|
112193
112813
|
}
|
|
112194
112814
|
else if (obj instanceof abaplint.Objects.WebMIME) {
|
|
112195
|
-
output.objects.push(...new handle_w3mi_1.HandleW3MI().runObject(obj, reg));
|
|
112815
|
+
output.objects.push(...new handle_w3mi_1.HandleW3MI(layout).runObject(obj, reg));
|
|
112196
112816
|
}
|
|
112197
112817
|
else if (obj instanceof abaplint.Objects.MessageClass) {
|
|
112198
112818
|
output.objects.push(...new handle_msag_1.HandleMSAG().runObject(obj, reg));
|
|
112199
112819
|
}
|
|
112200
|
-
else if (this.plugin !== undefined) {
|
|
112201
|
-
const handled = this.plugin.handleObject(obj, reg, this.options || {});
|
|
112202
|
-
if (handled !== undefined) {
|
|
112203
|
-
output.objects.push(...handled);
|
|
112204
|
-
pluginOutputs.push(...handled);
|
|
112205
|
-
}
|
|
112206
|
-
}
|
|
112207
112820
|
}
|
|
112208
|
-
|
|
112209
|
-
output.
|
|
112210
|
-
|
|
112821
|
+
output.initializationScript = new initialization_1.Initialization(layout).script(reg, dbSetup, this.options, false);
|
|
112822
|
+
output.initializationScript2 = new initialization_1.Initialization(layout).script(reg, dbSetup, this.options, true);
|
|
112823
|
+
for (const file of output.objects) {
|
|
112824
|
+
file.filename = layout.file(file.object, file.filename);
|
|
112825
|
+
}
|
|
112211
112826
|
return output;
|
|
112212
112827
|
}
|
|
112213
112828
|
// ///////////////////////////////
|
|
112214
112829
|
validate(reg) {
|
|
112215
|
-
const issues = new validation_1.Validation(this.options
|
|
112830
|
+
const issues = new validation_1.Validation(this.options).run(reg);
|
|
112216
112831
|
if (issues.length > 0) {
|
|
112217
112832
|
const messages = issues.map(i => i.getKey() + ", " +
|
|
112218
112833
|
i.getMessage() + ", " +
|
|
@@ -112274,6 +112889,7 @@ exports.escapeNamespaceFilename = escapeNamespaceFilename;
|
|
|
112274
112889
|
exports.escapeFilenameForImport = escapeFilenameForImport;
|
|
112275
112890
|
const abaplint = __importStar(__webpack_require__(/*! @abaplint/core */ "./node_modules/@abaplint/core/build/src/index.js"));
|
|
112276
112891
|
const handle_fugr_1 = __webpack_require__(/*! ./handlers/handle_fugr */ "./node_modules/@abaplint/transpiler/build/src/handlers/handle_fugr.js");
|
|
112892
|
+
const output_layout_1 = __webpack_require__(/*! ./output_layout */ "./node_modules/@abaplint/transpiler/build/src/output_layout.js");
|
|
112277
112893
|
function escapeNamespaceFilename(filename) {
|
|
112278
112894
|
// ES modules are resolved and cached as URLs. This means that special characters must be
|
|
112279
112895
|
// percent-encoded, such as # with %23 and ? with %3F.
|
|
@@ -112291,7 +112907,12 @@ function escapeFilenameForImport(filename) {
|
|
|
112291
112907
|
return filename.replace(/%/g, "%25").replace(/#/g, "%23");
|
|
112292
112908
|
}
|
|
112293
112909
|
class Initialization {
|
|
112294
|
-
|
|
112910
|
+
layout;
|
|
112911
|
+
constructor(layout = new output_layout_1.OutputLayout()) {
|
|
112912
|
+
this.layout = layout;
|
|
112913
|
+
// Flat output unless the caller supplies ownership information.
|
|
112914
|
+
}
|
|
112915
|
+
script(reg, dbSetup, options, useImport) {
|
|
112295
112916
|
let ret = "";
|
|
112296
112917
|
if (useImport === true) {
|
|
112297
112918
|
ret = `/* eslint-disable import/newline-after-import */
|
|
@@ -112334,28 +112955,24 @@ globalThis.abap = new runtime.ABAP();\n`;
|
|
|
112334
112955
|
}
|
|
112335
112956
|
ret += `}\n\n`;
|
|
112336
112957
|
ret += `await initializeABAP();\n\n`;
|
|
112337
|
-
ret += `${this.buildImports(reg, useImport, options
|
|
112958
|
+
ret += `${this.buildImports(reg, useImport, options)}`;
|
|
112338
112959
|
if (options?.setup?.postFunction !== undefined) {
|
|
112339
112960
|
ret += `\n\nawait setup.${options?.setup?.postFunction}();\n`;
|
|
112340
112961
|
}
|
|
112341
112962
|
return ret;
|
|
112342
112963
|
}
|
|
112343
|
-
buildImports(reg, useImport, options
|
|
112964
|
+
buildImports(reg, useImport, options) {
|
|
112344
112965
|
// note: ES modules are hoised, so use the dynamic import(), due to setting of globalThis.abap
|
|
112345
112966
|
// some sorting required: eg. a class constructor using constant from interface
|
|
112346
112967
|
const list = [];
|
|
112347
112968
|
const late = [];
|
|
112348
112969
|
const imp = (filename) => {
|
|
112349
|
-
|
|
112350
|
-
|
|
112351
|
-
|
|
112352
|
-
|
|
112353
|
-
|
|
112354
|
-
}
|
|
112970
|
+
const specifier = (0, output_layout_1.importPath)("init.mjs", filename);
|
|
112971
|
+
return {
|
|
112972
|
+
filename: specifier.split("/").pop(),
|
|
112973
|
+
code: useImport === true ? `import "${specifier}";` : `await import("${specifier}");`,
|
|
112974
|
+
};
|
|
112355
112975
|
};
|
|
112356
|
-
for (const pluginOutput of pluginOutputs || []) {
|
|
112357
|
-
list.push(imp(pluginOutput.filename.replace(/\.mjs$/i, "")));
|
|
112358
|
-
}
|
|
112359
112976
|
for (const obj of reg.getObjects()) {
|
|
112360
112977
|
if (obj instanceof abaplint.Objects.Table
|
|
112361
112978
|
|| obj instanceof abaplint.Objects.DataElement
|
|
@@ -112367,11 +112984,11 @@ globalThis.abap = new runtime.ABAP();\n`;
|
|
|
112367
112984
|
|| obj instanceof abaplint.Objects.TypePool
|
|
112368
112985
|
|| obj instanceof abaplint.Objects.TableType
|
|
112369
112986
|
|| obj instanceof abaplint.Objects.View) {
|
|
112370
|
-
list.push(imp(
|
|
112987
|
+
list.push(imp(this.layout.objectModule(obj)));
|
|
112371
112988
|
}
|
|
112372
112989
|
}
|
|
112373
112990
|
for (const obj of reg.getObjects()) {
|
|
112374
|
-
const name = imp(
|
|
112991
|
+
const name = imp(this.layout.objectModule(obj));
|
|
112375
112992
|
if (obj instanceof abaplint.Objects.Class
|
|
112376
112993
|
&& obj.getName().toUpperCase() !== "CL_ABAP_CHAR_UTILITIES"
|
|
112377
112994
|
&& this.hasClassConstructor(reg, obj)) {
|
|
@@ -112391,7 +113008,9 @@ globalThis.abap = new runtime.ABAP();\n`;
|
|
|
112391
113008
|
list.push(name);
|
|
112392
113009
|
}
|
|
112393
113010
|
}
|
|
112394
|
-
|
|
113011
|
+
// Folder names must not change the original module initialization order.
|
|
113012
|
+
list.sort((a, b) => a.filename < b.filename ? -1 : a.filename > b.filename ? 1 : 0);
|
|
113013
|
+
return [...list, ...late].map(entry => entry.code).join("\n");
|
|
112395
113014
|
}
|
|
112396
113015
|
// class constructors might make early use of eg. constants from interfaces
|
|
112397
113016
|
// sub classes will import() super classes and trigger a class constructor of the super
|
|
@@ -112543,6 +113162,89 @@ exports.DEFAULT_KEYWORDS = new Set([
|
|
|
112543
113162
|
|
|
112544
113163
|
/***/ },
|
|
112545
113164
|
|
|
113165
|
+
/***/ "./node_modules/@abaplint/transpiler/build/src/output_layout.js"
|
|
113166
|
+
/*!**********************************************************************!*\
|
|
113167
|
+
!*** ./node_modules/@abaplint/transpiler/build/src/output_layout.js ***!
|
|
113168
|
+
\**********************************************************************/
|
|
113169
|
+
(__unused_webpack_module, exports) {
|
|
113170
|
+
|
|
113171
|
+
"use strict";
|
|
113172
|
+
|
|
113173
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
113174
|
+
exports.OutputLayout = void 0;
|
|
113175
|
+
exports.importPath = importPath;
|
|
113176
|
+
/** Browser-safe paths: generated modules use POSIX paths on every platform. */
|
|
113177
|
+
class OutputLayout {
|
|
113178
|
+
grouped;
|
|
113179
|
+
objectFolders = new Map();
|
|
113180
|
+
sourceFolders = new Map();
|
|
113181
|
+
constructor(reg, folders) {
|
|
113182
|
+
this.grouped = folders !== undefined;
|
|
113183
|
+
if (folders === undefined) {
|
|
113184
|
+
return;
|
|
113185
|
+
}
|
|
113186
|
+
for (const [filename, folder] of folders) {
|
|
113187
|
+
this.sourceFolders.set(filename.toLowerCase(), folder);
|
|
113188
|
+
}
|
|
113189
|
+
for (const obj of reg?.getObjects() || []) {
|
|
113190
|
+
const owners = new Set(obj.getFiles().map(f => this.sourceFolders.get(f.getFilename().toLowerCase()))
|
|
113191
|
+
.filter((folder) => folder !== undefined));
|
|
113192
|
+
if (owners.size !== 1) {
|
|
113193
|
+
throw new Error("Ambiguous output ownership for " + obj.getType() + " " + obj.getName());
|
|
113194
|
+
}
|
|
113195
|
+
const folder = [...owners][0];
|
|
113196
|
+
this.objectFolders.set(this.key({ type: obj.getType(), name: obj.getName() }), folder);
|
|
113197
|
+
for (const file of obj.getFiles()) {
|
|
113198
|
+
// Class locals are merged into a single module.
|
|
113199
|
+
this.sourceFolders.set(file.getFilename().toLowerCase().replace(/\.locals_(def|imp)\.abap$/, ".locals.abap"), folder);
|
|
113200
|
+
}
|
|
113201
|
+
}
|
|
113202
|
+
}
|
|
113203
|
+
key(obj) {
|
|
113204
|
+
return obj.type.toUpperCase() + ":" + obj.name.toUpperCase();
|
|
113205
|
+
}
|
|
113206
|
+
file(obj, filename) {
|
|
113207
|
+
const folder = this.objectFolders.get(this.key(obj));
|
|
113208
|
+
if (this.grouped && folder === undefined) {
|
|
113209
|
+
throw new Error("Missing output ownership for " + obj.type + " " + obj.name);
|
|
113210
|
+
}
|
|
113211
|
+
if (folder !== undefined && (filename.startsWith("/") || /[\\:]/.test(filename)
|
|
113212
|
+
|| filename.split("/").some(segment => segment === "" || segment === "." || segment === ".."))) {
|
|
113213
|
+
throw new Error("Invalid output filename: " + filename);
|
|
113214
|
+
}
|
|
113215
|
+
return folder === undefined ? filename : folder + "/" + filename;
|
|
113216
|
+
}
|
|
113217
|
+
sourceModule(filename) {
|
|
113218
|
+
const folder = this.sourceFolders.get(filename.toLowerCase());
|
|
113219
|
+
if (this.grouped && folder === undefined) {
|
|
113220
|
+
throw new Error("Missing output ownership for source " + filename);
|
|
113221
|
+
}
|
|
113222
|
+
const module = filename.replace(/\.abap$/i, ".mjs").toLowerCase();
|
|
113223
|
+
return folder === undefined ? module : folder + "/" + module;
|
|
113224
|
+
}
|
|
113225
|
+
objectModule(obj, suffix = "") {
|
|
113226
|
+
const identifier = { name: obj.getName(), type: obj.getType() };
|
|
113227
|
+
const filename = obj.getName().toLowerCase().replace(/\//g, "#") + "." + obj.getType().toLowerCase() + suffix + ".mjs";
|
|
113228
|
+
return this.file(identifier, filename);
|
|
113229
|
+
}
|
|
113230
|
+
}
|
|
113231
|
+
exports.OutputLayout = OutputLayout;
|
|
113232
|
+
/** Escape each segment without turning directory separators into namespace markers. */
|
|
113233
|
+
function importPath(from, to) {
|
|
113234
|
+
const source = from.split("/").slice(0, -1);
|
|
113235
|
+
const target = to.split("/");
|
|
113236
|
+
while (source.length > 0 && target.length > 0 && source[0] === target[0]) {
|
|
113237
|
+
source.shift();
|
|
113238
|
+
target.shift();
|
|
113239
|
+
}
|
|
113240
|
+
const relative = [...source.map(() => ".."), ...target].join("/");
|
|
113241
|
+
const escaped = relative.split("/").map(segment => encodeURIComponent(segment)).join("/");
|
|
113242
|
+
return escaped.startsWith("../") ? escaped : "./" + escaped;
|
|
113243
|
+
}
|
|
113244
|
+
//# sourceMappingURL=output_layout.js.map
|
|
113245
|
+
|
|
113246
|
+
/***/ },
|
|
113247
|
+
|
|
112546
113248
|
/***/ "./node_modules/@abaplint/transpiler/build/src/rearranger.js"
|
|
112547
113249
|
/*!*******************************************************************!*\
|
|
112548
113250
|
!*** ./node_modules/@abaplint/transpiler/build/src/rearranger.js ***!
|
|
@@ -113405,6 +114107,22 @@ throw error;
|
|
|
113405
114107
|
}
|
|
113406
114108
|
})())`;
|
|
113407
114109
|
}
|
|
114110
|
+
/** ASSIGN of a statically specified data object, e.g. a variable, an attribute or an offset/length,
|
|
114111
|
+
* does not set sy-subrc, a dereference, a table expression or COMPONENT does */
|
|
114112
|
+
isStaticDataObject(node, source) {
|
|
114113
|
+
const concat = node.concatTokens().toUpperCase();
|
|
114114
|
+
if (source === undefined
|
|
114115
|
+
|| concat.startsWith("ASSIGN COMPONENT ")
|
|
114116
|
+
|| concat.includes(" INCREMENT ")
|
|
114117
|
+
|| concat.includes(" ELSE UNASSIGN")
|
|
114118
|
+
|| source.findFirstExpression(abaplint.Expressions.Dereference) !== undefined
|
|
114119
|
+
|| source.findFirstExpression(abaplint.Expressions.TableExpression) !== undefined) {
|
|
114120
|
+
return false;
|
|
114121
|
+
}
|
|
114122
|
+
// field symbols are left as they are, not measured
|
|
114123
|
+
const first = source.findFirstExpression(abaplint.Expressions.FieldChain)?.getFirstChild();
|
|
114124
|
+
return first !== undefined && !(first.get() instanceof abaplint.Expressions.SourceFieldSymbol);
|
|
114125
|
+
}
|
|
113408
114126
|
transpile(node, traversal) {
|
|
113409
114127
|
const assignSource = node.findDirectExpression(abaplint.Expressions.AssignSource);
|
|
113410
114128
|
const sourceExpressions = assignSource?.findDirectExpressionsMulti([abaplint.Expressions.Source, abaplint.Expressions.SimpleSource3]) || [];
|
|
@@ -113444,6 +114162,9 @@ throw error;
|
|
|
113444
114162
|
}
|
|
113445
114163
|
else {
|
|
113446
114164
|
options.push("source: " + sources.pop());
|
|
114165
|
+
if (this.isStaticDataObject(node, sourceExprForCheck)) {
|
|
114166
|
+
options.push("keepSubrc: true");
|
|
114167
|
+
}
|
|
113447
114168
|
}
|
|
113448
114169
|
}
|
|
113449
114170
|
else {
|
|
@@ -114475,7 +115196,7 @@ static INTERNAL_TYPE = 'CLAS';
|
|
|
114475
115196
|
static INTERNAL_NAME = '${traversal.buildInternalName(token.getStr(), def)}';
|
|
114476
115197
|
static IMPLEMENTED_INTERFACES = [${this.findImplementedByClass(traversal, def, scope).map(e => `"` + e.toUpperCase() + `"`).join(",")}];
|
|
114477
115198
|
static ATTRIBUTES = {${Array.from(traversal.buildAttributes(def, scope)).join(",\n")}};
|
|
114478
|
-
static METHODS = {${traversal.buildMethods(def).join(",\n")}};`, node, traversal);
|
|
115199
|
+
static METHODS = {${traversal.buildMethods(def, scope).join(",\n")}};`, node, traversal);
|
|
114479
115200
|
}
|
|
114480
115201
|
findImplementedInterface(traversal, def, scope) {
|
|
114481
115202
|
if (def === undefined || scope === undefined) {
|
|
@@ -118867,6 +119588,16 @@ class MethodImplementationTranspiler {
|
|
|
118867
119588
|
else {
|
|
118868
119589
|
after += `let ${varPrefixed} = ${unique}?.${varName};\n`;
|
|
118869
119590
|
}
|
|
119591
|
+
if (passByValue === true) {
|
|
119592
|
+
// pass by value: the method works on its own copy, also for a generic type,
|
|
119593
|
+
// which keeps the type of the actual parameter.
|
|
119594
|
+
// A field symbol that is unassigned or assigned with CASTING is passed on as it is
|
|
119595
|
+
after += `if (${varPrefixed} instanceof abap.types.FieldSymbol) {
|
|
119596
|
+
if (${varPrefixed}.getPointer()?.clone !== undefined) { ${varPrefixed} = ${varPrefixed}.getPointer().clone(); }
|
|
119597
|
+
} else if (${unique}?.${varName} !== undefined && ${varPrefixed}?.clone !== undefined) {
|
|
119598
|
+
${varPrefixed} = ${varPrefixed}.clone();
|
|
119599
|
+
}\n`;
|
|
119600
|
+
}
|
|
118870
119601
|
if (type instanceof abaplint.BasicTypes.NumericGenericType) {
|
|
118871
119602
|
after += `if (${varPrefixed}.constructor.name === "Character") {
|
|
118872
119603
|
${varPrefixed} = ${transpile_types_1.TranspileTypes.toType(identifier.getType())};
|
|
@@ -121228,8 +121959,18 @@ class SelectTranspiler {
|
|
|
121228
121959
|
const having = node.findDirectExpression(abaplint.Expressions.Select)
|
|
121229
121960
|
?.findDirectExpression(abaplint.Expressions.SQLHaving);
|
|
121230
121961
|
const havingCond = having?.findFirstExpression(abaplint.Expressions.SQLCond);
|
|
121962
|
+
let dynamicHaving;
|
|
121231
121963
|
if (havingCond) {
|
|
121232
|
-
|
|
121964
|
+
const dynamic = havingCond.findFirstExpression(abaplint.Expressions.Dynamic);
|
|
121965
|
+
const chain = dynamic?.findFirstExpression(abaplint.Expressions.FieldChain);
|
|
121966
|
+
if (chain && havingCond.concatTokens() === dynamic?.concatTokens()) {
|
|
121967
|
+
dynamicHaving = dynamic;
|
|
121968
|
+
const code = new expressions_1.FieldChainTranspiler(false).transpile(chain, traversal).getCode();
|
|
121969
|
+
select += `" + ${this.dynamicHavingClause(code)} + " `;
|
|
121970
|
+
}
|
|
121971
|
+
else {
|
|
121972
|
+
select += "HAVING " + new expressions_1.SQLCondTranspiler().transpile(havingCond, traversal, table).getCode() + " ";
|
|
121973
|
+
}
|
|
121233
121974
|
}
|
|
121234
121975
|
const upTo = node.findFirstExpression(abaplint.Expressions.SQLUpTo);
|
|
121235
121976
|
if (upTo) {
|
|
@@ -121249,6 +121990,9 @@ class SelectTranspiler {
|
|
|
121249
121990
|
const groupByDynamics = new Set(groupBy?.findAllExpressionsRecursive(abaplint.Expressions.Dynamic) || []);
|
|
121250
121991
|
const orderByDynamics = new Set(orderBy?.findAllExpressionsRecursive(abaplint.Expressions.Dynamic) || []);
|
|
121251
121992
|
for (const d of node.findAllExpressionsRecursive(abaplint.Expressions.Dynamic)) {
|
|
121993
|
+
if (d === dynamicHaving) {
|
|
121994
|
+
continue;
|
|
121995
|
+
}
|
|
121252
121996
|
const chain = d.findFirstExpression(abaplint.Expressions.FieldChain);
|
|
121253
121997
|
if (chain) {
|
|
121254
121998
|
const search = d.concatTokens();
|
|
@@ -121405,6 +122149,13 @@ abap.builtin.sy.get().dbcnt.set(${target}.getArrayLength());
|
|
|
121405
122149
|
+ ` ? (${code}.array().length === 0 ? "" : "${keyword} " + ${code}.array().map(row => row.get()).join(", "))`
|
|
121406
122150
|
+ ` : (("" + ${code}.get()).trim() === "" ? "" : "${keyword} " + ${code}.get()))`;
|
|
121407
122151
|
}
|
|
122152
|
+
dynamicHavingClause(code) {
|
|
122153
|
+
return `((value) => {
|
|
122154
|
+
const condition = value instanceof abap.types.Table || value instanceof abap.types.HashedTable
|
|
122155
|
+
? value.array().map(row => row.get()).join(" ") : value.get();
|
|
122156
|
+
return condition.trim() === "" ? "" : "HAVING " + abap.expandDynamic(condition, (name) => {try { return eval(name);} catch {}});
|
|
122157
|
+
})(${code})`;
|
|
122158
|
+
}
|
|
121408
122159
|
isWhereExpression(node, expression) {
|
|
121409
122160
|
// check if previous token before sqlCond is "WHERE". It could also be "ON" in case of join condition
|
|
121410
122161
|
let prevToken;
|
|
@@ -124645,8 +125396,11 @@ class InterfaceTranspiler {
|
|
|
124645
125396
|
ret += `static INTERNAL_TYPE = 'INTF';\n`;
|
|
124646
125397
|
ret += `static INTERNAL_NAME = '${traversal.buildInternalName(token.getStr(), def)}';\n`;
|
|
124647
125398
|
ret += `static ATTRIBUTES = {${Array.from(traversal.buildAttributes(def, scope)).join(",\n")}};\n`;
|
|
124648
|
-
ret += `static METHODS = {${traversal.buildMethods(def).join(",\n")}};\n`;
|
|
124649
|
-
|
|
125399
|
+
ret += `static METHODS = {${traversal.buildMethods(def, scope).join(",\n")}};\n`;
|
|
125400
|
+
const interfaces = def?.getImplementing().map(i => `"${i.name.toUpperCase()}"`) || [];
|
|
125401
|
+
if (interfaces.length > 0) {
|
|
125402
|
+
ret += `static IMPLEMENTED_INTERFACES = [${interfaces.join(",")}];\n`;
|
|
125403
|
+
}
|
|
124650
125404
|
}
|
|
124651
125405
|
else if (c instanceof abaplint.Nodes.StatementNode && c.get() instanceof abaplint.Statements.EndInterface) {
|
|
124652
125406
|
ret += "}\n";
|
|
@@ -125441,8 +126195,22 @@ class TranspileTypes {
|
|
|
125441
126195
|
if (type instanceof abaplint.BasicTypes.ObjectReferenceType
|
|
125442
126196
|
|| type instanceof abaplint.BasicTypes.GenericObjectReferenceType) {
|
|
125443
126197
|
resolved = "ABAPObject";
|
|
125444
|
-
|
|
125445
|
-
|
|
126198
|
+
const qualifiedName = type.getQualifiedName()
|
|
126199
|
+
?? (type instanceof abaplint.BasicTypes.ObjectReferenceType ? type.getIdentifierName() : undefined);
|
|
126200
|
+
let RTTIName = type.getRTTIName();
|
|
126201
|
+
if (type instanceof abaplint.BasicTypes.ObjectReferenceType && RTTIName === undefined) {
|
|
126202
|
+
const id = type.getIdentifier();
|
|
126203
|
+
// NEW and CAST can omit metadata; recover it from the referenced definition.
|
|
126204
|
+
const [name, kind] = id.getFilename().split("/").pop().replace(/#/g, "/").split(".");
|
|
126205
|
+
const local = (id instanceof abaplint.Types.ClassDefinition || id instanceof abaplint.Types.InterfaceDefinition)
|
|
126206
|
+
&& id.isGlobal() === false;
|
|
126207
|
+
const prefix = local && kind === "prog" ? "\\PROGRAM=" + name
|
|
126208
|
+
: local && kind === "clas" ? "\\CLASS-POOL=" + name : "";
|
|
126209
|
+
const category = id instanceof abaplint.Types.InterfaceDefinition || kind === "intf" ? "INTERFACE" : "CLASS";
|
|
126210
|
+
RTTIName = prefix + "\\" + category + "=" + id.getName();
|
|
126211
|
+
}
|
|
126212
|
+
extra = "{qualifiedName: " + JSON.stringify(qualifiedName?.toUpperCase()) +
|
|
126213
|
+
", RTTIName: " + JSON.stringify(RTTIName?.toUpperCase()) + "}";
|
|
125446
126214
|
}
|
|
125447
126215
|
else if (type instanceof abaplint.BasicTypes.TableType) {
|
|
125448
126216
|
resolved = "Table";
|
|
@@ -125570,6 +126338,11 @@ class TranspileTypes {
|
|
|
125570
126338
|
resolved = "Packed";
|
|
125571
126339
|
extra = "{length: 8, decimals: 2}";
|
|
125572
126340
|
}
|
|
126341
|
+
else if (type instanceof abaplint.BasicTypes.PGenericType) {
|
|
126342
|
+
// if not supplied its a P LENGTH 8 DECIMALS 0
|
|
126343
|
+
resolved = "Packed";
|
|
126344
|
+
extra = "{length: 8, decimals: 0}";
|
|
126345
|
+
}
|
|
125573
126346
|
else if (type instanceof abaplint.BasicTypes.XStringType) {
|
|
125574
126347
|
resolved = "XString";
|
|
125575
126348
|
if (type.getQualifiedName() !== undefined) {
|
|
@@ -125995,7 +126768,7 @@ class Traversal {
|
|
|
125995
126768
|
}
|
|
125996
126769
|
return undefined;
|
|
125997
126770
|
}
|
|
125998
|
-
buildMethods(def) {
|
|
126771
|
+
buildMethods(def, scope) {
|
|
125999
126772
|
const methods = [];
|
|
126000
126773
|
if (def === undefined) {
|
|
126001
126774
|
return methods;
|
|
@@ -126006,29 +126779,57 @@ class Traversal {
|
|
|
126006
126779
|
throw new Error("buildMethods: unexpected undefined, " + def.getName());
|
|
126007
126780
|
}
|
|
126008
126781
|
for (const m of methodDefinitions.getAll()) {
|
|
126009
|
-
|
|
126010
|
-
|
|
126011
|
-
|
|
126012
|
-
|
|
126013
|
-
|
|
126014
|
-
|
|
126015
|
-
|
|
126016
|
-
|
|
126017
|
-
|
|
126018
|
-
|
|
126019
|
-
|
|
126020
|
-
|
|
126021
|
-
pKind = m.getParameters().getExporting().find((t) => { return t.getName() === p.getName(); }) ? "E" : "";
|
|
126022
|
-
}
|
|
126023
|
-
if (pKind === "") {
|
|
126024
|
-
pKind = m.getParameters().getReturning()?.getName() === p.getName() ? "R" : "";
|
|
126025
|
-
}
|
|
126026
|
-
parameters.push(`"${p.getName().toUpperCase()}": {"type": () => {return ${type};}, "is_optional": "${optional}", "parm_kind": "${pKind}", "type_name": "${p.getType().constructor.name}"}`);
|
|
126782
|
+
methods.push(this.buildMethod(m.getName(), m, m.getVisibility()));
|
|
126783
|
+
}
|
|
126784
|
+
// an alias for an interface method is listed under its own name, pointing to the method
|
|
126785
|
+
for (const a of def.getAliases() || []) {
|
|
126786
|
+
const [intfName, methodName] = a.getComponent().split("~");
|
|
126787
|
+
if (methodName === undefined) {
|
|
126788
|
+
continue;
|
|
126789
|
+
}
|
|
126790
|
+
const aliased = this.findInterfaceDefinition(intfName, scope)?.getMethodDefinitions()?.getByName(methodName);
|
|
126791
|
+
if (aliased === undefined) {
|
|
126792
|
+
// not a method, or the interface is unknown
|
|
126793
|
+
continue;
|
|
126027
126794
|
}
|
|
126028
|
-
methods.push(
|
|
126795
|
+
methods.push(this.buildMethod(a.getName(), aliased, a.getVisibility(), a.getComponent()));
|
|
126029
126796
|
}
|
|
126030
126797
|
return methods;
|
|
126031
126798
|
}
|
|
126799
|
+
buildMethod(name, m, visibility, aliasFor) {
|
|
126800
|
+
const optionalNames = m.getParameters().getOptional().map(o => o.toUpperCase());
|
|
126801
|
+
const parameters = [];
|
|
126802
|
+
for (const p of m.getParameters().getAll()) {
|
|
126803
|
+
const type = transpile_types_1.TranspileTypes.toType(p.getType());
|
|
126804
|
+
const optional = optionalNames.includes(p.getName().toUpperCase()) ? "X" : " ";
|
|
126805
|
+
let pKind = "";
|
|
126806
|
+
if (pKind === "") {
|
|
126807
|
+
pKind = m.getParameters().getImporting().find((t) => { return t.getName() === p.getName(); }) ? "I" : "";
|
|
126808
|
+
}
|
|
126809
|
+
if (pKind === "") {
|
|
126810
|
+
pKind = m.getParameters().getChanging().find((t) => { return t.getName() === p.getName(); }) ? "C" : "";
|
|
126811
|
+
}
|
|
126812
|
+
if (pKind === "") {
|
|
126813
|
+
pKind = m.getParameters().getExporting().find((t) => { return t.getName() === p.getName(); }) ? "E" : "";
|
|
126814
|
+
}
|
|
126815
|
+
if (pKind === "") {
|
|
126816
|
+
pKind = m.getParameters().getReturning()?.getName() === p.getName() ? "R" : "";
|
|
126817
|
+
}
|
|
126818
|
+
parameters.push(`"${p.getName().toUpperCase()}": {"type": () => {return ${type};}, "is_optional": "${optional}", "parm_kind": "${pKind}", "type_name": "${p.getType().constructor.name}"}`);
|
|
126819
|
+
}
|
|
126820
|
+
// only written when set, a method without them is described as before
|
|
126821
|
+
let extra = "";
|
|
126822
|
+
if (m.isStatic() === true) {
|
|
126823
|
+
extra += `"is_class": "X", `;
|
|
126824
|
+
}
|
|
126825
|
+
if (m.getRaising().length > 0) {
|
|
126826
|
+
extra += `"exceptions": [${m.getRaising().map(e => `"${e.toUpperCase()}"`).join(", ")}], `;
|
|
126827
|
+
}
|
|
126828
|
+
if (aliasFor !== undefined) {
|
|
126829
|
+
extra += `"alias_for": "${aliasFor.toUpperCase()}", `;
|
|
126830
|
+
}
|
|
126831
|
+
return `"${name.toUpperCase()}": {"visibility": "${this.mapVisibility(visibility)}", ${extra}"parameters": {${parameters.join(", ")}}}`;
|
|
126832
|
+
}
|
|
126032
126833
|
mapVisibility(vis) {
|
|
126033
126834
|
switch (vis) {
|
|
126034
126835
|
case abaplint.Visibility.Private:
|
|
@@ -126922,8 +127723,13 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
|
126922
127723
|
exports.UnitTest = void 0;
|
|
126923
127724
|
/* eslint-disable max-len */
|
|
126924
127725
|
const abaplint = __importStar(__webpack_require__(/*! @abaplint/core */ "./node_modules/@abaplint/core/build/src/index.js"));
|
|
126925
|
-
const
|
|
127726
|
+
const output_layout_1 = __webpack_require__(/*! ./output_layout */ "./node_modules/@abaplint/transpiler/build/src/output_layout.js");
|
|
126926
127727
|
class UnitTest {
|
|
127728
|
+
layout;
|
|
127729
|
+
constructor(layout = new output_layout_1.OutputLayout()) {
|
|
127730
|
+
this.layout = layout;
|
|
127731
|
+
// Test runners live at the output root.
|
|
127732
|
+
}
|
|
126927
127733
|
unitTestScriptOpen(reg, _skip) {
|
|
126928
127734
|
let ret = `/* eslint-disable curly */
|
|
126929
127735
|
import fs from "fs";
|
|
@@ -126944,7 +127750,7 @@ async function run() {
|
|
|
126944
127750
|
}
|
|
126945
127751
|
const hasTestFile = obj.getFiles().some(f => { return f.getFilename().includes(".testclasses."); });
|
|
126946
127752
|
if (hasTestFile === true) {
|
|
126947
|
-
ret += ` await import("
|
|
127753
|
+
ret += ` await import("${(0, output_layout_1.importPath)("index.mjs", this.layout.objectModule(obj, ".testclasses"))}");\n`;
|
|
126948
127754
|
}
|
|
126949
127755
|
for (const file of obj.getABAPFiles()) {
|
|
126950
127756
|
for (const def of file.getInfo().listClassDefinitions()) {
|
|
@@ -127006,7 +127812,7 @@ run().then(() => {
|
|
|
127006
127812
|
}
|
|
127007
127813
|
tests.push({
|
|
127008
127814
|
obj,
|
|
127009
|
-
filename:
|
|
127815
|
+
filename: `${(0, output_layout_1.importPath)("index.mjs", this.layout.objectModule(obj, ".testclasses"))}`,
|
|
127010
127816
|
localClass: def.name.toLowerCase(),
|
|
127011
127817
|
riskLevel: def.riskLevel,
|
|
127012
127818
|
duration: def.duration,
|
|
@@ -127151,8 +127957,12 @@ const core_1 = __webpack_require__(/*! @abaplint/core */ "./node_modules/@abapli
|
|
|
127151
127957
|
const types_1 = __webpack_require__(/*! ./types */ "./node_modules/@abaplint/transpiler/build/src/types.js");
|
|
127152
127958
|
const defaultAllowedObjectTypes = [
|
|
127153
127959
|
"APIS",
|
|
127960
|
+
"APLO",
|
|
127154
127961
|
"AUTH",
|
|
127962
|
+
"BDEF",
|
|
127155
127963
|
"CLAS",
|
|
127964
|
+
"DDLS",
|
|
127965
|
+
"DDLX",
|
|
127156
127966
|
"DEVC",
|
|
127157
127967
|
"DOMA",
|
|
127158
127968
|
"DTEL",
|
|
@@ -127174,13 +127984,19 @@ const defaultAllowedObjectTypes = [
|
|
|
127174
127984
|
"PARA",
|
|
127175
127985
|
"PINF",
|
|
127176
127986
|
"PROG",
|
|
127987
|
+
"SAJC",
|
|
127988
|
+
"SAJT",
|
|
127989
|
+
"SCO2",
|
|
127177
127990
|
"WAPA",
|
|
127178
127991
|
"SHLP",
|
|
127179
127992
|
"SHMA",
|
|
127993
|
+
"SIA6",
|
|
127180
127994
|
"SICF",
|
|
127181
127995
|
"SMIM",
|
|
127182
127996
|
"SPLO",
|
|
127183
127997
|
"SRFC",
|
|
127998
|
+
"SRVB",
|
|
127999
|
+
"SRVD",
|
|
127184
128000
|
"SUSC",
|
|
127185
128001
|
"SUSH",
|
|
127186
128002
|
"SUSO",
|
|
@@ -127256,10 +128072,8 @@ exports.config = {
|
|
|
127256
128072
|
// hmm this ^ is okay? since lines will be prefixed with "abap.builtin"?
|
|
127257
128073
|
class Validation {
|
|
127258
128074
|
options;
|
|
127259
|
-
|
|
127260
|
-
constructor(options, plugin) {
|
|
128075
|
+
constructor(options) {
|
|
127261
128076
|
this.options = options;
|
|
127262
|
-
this.plugin = plugin;
|
|
127263
128077
|
}
|
|
127264
128078
|
run(reg) {
|
|
127265
128079
|
if (this.options?.ignoreSyntaxCheck === true) {
|
|
@@ -127269,13 +128083,6 @@ class Validation {
|
|
|
127269
128083
|
exports.config.rules.check_syntax = true;
|
|
127270
128084
|
}
|
|
127271
128085
|
exports.config.rules.forbidden_identifier.check = ["^unique\\d+$"];
|
|
127272
|
-
const allowed = [...defaultAllowedObjectTypes];
|
|
127273
|
-
for (const type of this.plugin?.objectTypes() || []) {
|
|
127274
|
-
if (allowed.includes(type.toUpperCase()) === false) {
|
|
127275
|
-
allowed.push(type.toUpperCase());
|
|
127276
|
-
}
|
|
127277
|
-
}
|
|
127278
|
-
exports.config.rules.allowed_object_types.allowed = allowed;
|
|
127279
128086
|
if (this.options?.unknownTypes === types_1.UnknownTypesEnum.runtimeError) {
|
|
127280
128087
|
// this is not a constant, just a regex that happens to not match anything
|
|
127281
128088
|
exports.config.syntax.errorNamespace = "VOID_EVERYTHING";
|
|
@@ -130761,17 +131568,6 @@ module.exports = require("fs");
|
|
|
130761
131568
|
|
|
130762
131569
|
/***/ },
|
|
130763
131570
|
|
|
130764
|
-
/***/ "module"
|
|
130765
|
-
/*!*************************!*\
|
|
130766
|
-
!*** external "module" ***!
|
|
130767
|
-
\*************************/
|
|
130768
|
-
(module) {
|
|
130769
|
-
|
|
130770
|
-
"use strict";
|
|
130771
|
-
module.exports = require("module");
|
|
130772
|
-
|
|
130773
|
-
/***/ },
|
|
130774
|
-
|
|
130775
131571
|
/***/ "node:events"
|
|
130776
131572
|
/*!******************************!*\
|
|
130777
131573
|
!*** external "node:events" ***!
|