UNPKG

remote-abap-compiler-cli

Version:
158 lines (156 loc) 6.58 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const abap_adt_api_1 = require("abap-adt-api"); const randomstring_1 = __importDefault(require("randomstring")); class CompilationRequest { constructor(url, user, client, password) { this.url = url; this.user = user; this.client = client; this.password = password; this.adtClient = new abap_adt_api_1.ADTClient(url, user, password, client, "EN", { rejectUnauthorized: false }); this.className = "RAC_" + randomstring_1.default.generate({ capitalization: "uppercase", charset: "alphanumeric", length: 26, }); this.classUrl = "/sap/bc/adt/oo/classes/" + this.className.toLowerCase(); } compile(code) { return __awaiter(this, void 0, void 0, function* () { yield this.cleanup(true); let mappedResult; try { yield this.createClass(); const result = yield this.putClassSource(this.getGlobalClassSource(), code); mappedResult = this.mapToCompilationResult(result); if (mappedResult.success) { mappedResult.output = yield this.runClass(); } } finally { yield this.cleanup(); } return mappedResult; }); } cleanup(ignoreError = false) { return __awaiter(this, void 0, void 0, function* () { try { this.adtClient.stateful = abap_adt_api_1.session_types.stateful; const lock = yield this.adtClient.lock(this.classUrl); yield this.adtClient.deleteObject(this.classUrl, lock.LOCK_HANDLE); yield this.adtClient.dropSession(); } catch (error) { if (!ignoreError) { throw error; } } }); } createClass() { return __awaiter(this, void 0, void 0, function* () { yield this.adtClient.statelessClone.createObject("CLAS/OC", this.className, "$TMP", "remote ABAP compiler", "/sap/bc/adt/packages/$TMP"); }); } getGlobalClassSource() { const source = `class ${this.className} definition public create public final. public section. interfaces if_oo_adt_classrun. endclass. class ${this.className} implementation. method if_oo_adt_classrun~main. new main( )->run( out ). endmethod. endclass.`; return source; } putClassSource(globalClass, localTypes) { return __awaiter(this, void 0, void 0, function* () { this.adtClient.stateful = abap_adt_api_1.session_types.stateful; const lock = yield this.adtClient.lock(this.classUrl); yield this.adtClient.setObjectSource(this.classUrl + "/source/main", globalClass, lock.LOCK_HANDLE); yield this.adtClient.setObjectSource(this.classUrl + "/includes/implementations", localTypes, lock.LOCK_HANDLE); yield this.adtClient.dropSession(); const result = yield this.adtClient.activate(this.className, this.classUrl); return result; }); } mapToCompilationResult(activationResult) { if (!activationResult.success && activationResult.messages.length > 0) { return { className: this.className, errors: activationResult.messages.map(this.mapErrorMessages.bind(this)), success: activationResult.success, }; } return { className: this.className, success: activationResult.success, }; } mapErrorMessages(message) { const mainMethodErrorTag = `Class ${this.className}, Method IF_OO_ADT_CLASSRUN~MAIN`; if (message.objDescr === mainMethodErrorTag) { return this.mapErrorFromGlobalClass(message); } else { return this.mapErrorFromLocalTypesInclude(message); } } mapErrorFromLocalTypesInclude(message) { const search = /#start=(\d+),(\d+)/g; const match = search.exec(message.href); if (match !== null) { return { errorMessage: message.shortText, line: parseInt(match[1], 10), offset: parseInt(match[2], 10), }; } else { return { errorMessage: message.shortText, line: -1, offset: -1, }; } } mapErrorFromGlobalClass(message) { if (message.shortText === "Type \"MAIN\" is unknown." || message.shortText === "Method \"RUN\" is unknown or PROTECTED or PRIVATE.") { return { errorMessage: "Missing class named \"MAIN\" with public method \"RUN\".", line: -1, offset: -1, }; } else { const defaultErrorMessage = "The method \"RUN\" of class \"MAIN\" " + "must have exactly one importing parameter of type \"REF TO IF_OO_ADT_CLASSRUN_OUT\"."; return { errorMessage: defaultErrorMessage, line: -1, offset: -1, }; } } runClass() { return __awaiter(this, void 0, void 0, function* () { return this.adtClient.runClass(this.className); }); } } exports.CompilationRequest = CompilationRequest;