@abaplint/cli 2.120.50 → 2.120.52
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/build/cli.js +223 -13
- package/package.json +2 -2
package/build/cli.js
CHANGED
|
@@ -53,6 +53,13 @@ const BUFS = new Set([
|
|
|
53
53
|
CH_DOT, CH_COMMA, CH_COLON, 40 /* ( */, 41 /* ) */, 91 /* [ */,
|
|
54
54
|
93 /* ] */, 43 /* + */, CH_AT
|
|
55
55
|
]);
|
|
56
|
+
// characters that may follow the closing "'", "`" or "|" of a literal, anything else
|
|
57
|
+
// is a syntax error, "There must be a space or equivalent character after ...",
|
|
58
|
+
// note that "(" is allowed, ie. text elements like 'text'(001)
|
|
59
|
+
const AFTER_LITERAL = new Set([
|
|
60
|
+
EOF, CH_SPACE, CH_TAB, CH_NL, CH_DOT, CH_COMMA, CH_COLON, CH_DQUOTE,
|
|
61
|
+
40 /* ( */, 41 /* ) */, 91 /* [ */, 93 /* ] */
|
|
62
|
+
]);
|
|
56
63
|
class Lexer {
|
|
57
64
|
run(file, virtual) {
|
|
58
65
|
this.virtual = virtual;
|
|
@@ -332,7 +339,11 @@ class Lexer {
|
|
|
332
339
|
&& ahead !== CH_BACKTICK
|
|
333
340
|
&& this.buffer.countIsEven(CH_BACKTICK)) {
|
|
334
341
|
// end of ping
|
|
335
|
-
|
|
342
|
+
if (AFTER_LITERAL.has(ahead)) {
|
|
343
|
+
this.add();
|
|
344
|
+
}
|
|
345
|
+
// else: no separator after the literal, keep the buffer so the following
|
|
346
|
+
// characters are glued onto the token, the parser will report the error
|
|
336
347
|
if (ahead === CH_DQUOTE) {
|
|
337
348
|
this.m = ModeComment;
|
|
338
349
|
}
|
|
@@ -345,7 +356,9 @@ class Lexer {
|
|
|
345
356
|
&& (current === CH_PIPE || current === CH_LBRACE)
|
|
346
357
|
&& (stream.prevChar() !== CH_BACKSLASH || (stream.prevPrevChar() === CH_BACKSLASH && stream.prevChar() === CH_BACKSLASH))) {
|
|
347
358
|
// end of template
|
|
348
|
-
|
|
359
|
+
if (current === CH_LBRACE || AFTER_LITERAL.has(ahead)) {
|
|
360
|
+
this.add();
|
|
361
|
+
}
|
|
349
362
|
this.m = ModeNormal;
|
|
350
363
|
}
|
|
351
364
|
else if (this.m === ModeTemplate
|
|
@@ -360,7 +373,9 @@ class Lexer {
|
|
|
360
373
|
&& ahead !== CH_QUOTE
|
|
361
374
|
&& this.buffer.countIsEven(CH_QUOTE)) {
|
|
362
375
|
// end of string
|
|
363
|
-
|
|
376
|
+
if (AFTER_LITERAL.has(ahead)) {
|
|
377
|
+
this.add();
|
|
378
|
+
}
|
|
364
379
|
if (ahead === CH_DQUOTE) {
|
|
365
380
|
this.m = ModeComment;
|
|
366
381
|
}
|
|
@@ -27714,6 +27729,20 @@ class TypeUtils {
|
|
|
27714
27729
|
|| node.findFirstExpression(Expressions.ArithOperator) !== undefined;
|
|
27715
27730
|
return calculated;
|
|
27716
27731
|
}
|
|
27732
|
+
// a character constant is only assignable to a hexadecimal target if it can be
|
|
27733
|
+
// interpreted as a hexadecimal value
|
|
27734
|
+
isHexConstant(node) {
|
|
27735
|
+
const constant = node === null || node === void 0 ? void 0 : node.concatTokens();
|
|
27736
|
+
if (constant === undefined) {
|
|
27737
|
+
return true;
|
|
27738
|
+
}
|
|
27739
|
+
if ((constant.startsWith("'") && constant.endsWith("'"))
|
|
27740
|
+
|| (constant.startsWith("`") && constant.endsWith("`"))) {
|
|
27741
|
+
const value = constant.substring(1, constant.length - 1);
|
|
27742
|
+
return value.length > 0 && /^[0-9A-Fa-f]+$/.test(value);
|
|
27743
|
+
}
|
|
27744
|
+
return true;
|
|
27745
|
+
}
|
|
27717
27746
|
isAssignableNew(source, target, node) {
|
|
27718
27747
|
const calculated = (node === null || node === void 0 ? void 0 : node.findFirstExpression(Expressions.ArithOperator)) !== undefined;
|
|
27719
27748
|
if (calculated && source instanceof basic_1.HexType && target instanceof basic_1.IntegerType) {
|
|
@@ -27779,7 +27808,7 @@ class TypeUtils {
|
|
|
27779
27808
|
}
|
|
27780
27809
|
else if (target instanceof basic_1.XStringType) {
|
|
27781
27810
|
if (((_d = source.getAbstractTypeData()) === null || _d === void 0 ? void 0 : _d.derivedFromConstant) === true) {
|
|
27782
|
-
return (node
|
|
27811
|
+
return this.isHexConstant(node);
|
|
27783
27812
|
}
|
|
27784
27813
|
return false;
|
|
27785
27814
|
}
|
|
@@ -34711,6 +34740,7 @@ class Source {
|
|
|
34711
34740
|
return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
|
|
34712
34741
|
}
|
|
34713
34742
|
this.addIfInferred(node, input, foundType);
|
|
34743
|
+
this.traverseRemainingChildren(children, input);
|
|
34714
34744
|
return foundType;
|
|
34715
34745
|
}
|
|
34716
34746
|
case "REF":
|
|
@@ -70549,7 +70579,7 @@ class Registry {
|
|
|
70549
70579
|
}
|
|
70550
70580
|
static abaplintVersion() {
|
|
70551
70581
|
// magic, see build script "version.js"
|
|
70552
|
-
return "2.120.
|
|
70582
|
+
return "2.120.52";
|
|
70553
70583
|
}
|
|
70554
70584
|
getDDICReferences() {
|
|
70555
70585
|
return this.ddicReferences;
|
|
@@ -78686,15 +78716,19 @@ ${indentation}${uniqueName} = ${source.concatTokens()}.\n${indentation}`);
|
|
|
78686
78716
|
continue;
|
|
78687
78717
|
}
|
|
78688
78718
|
const condition = this.tableCondition(tableExpression);
|
|
78689
|
-
|
|
78719
|
+
// ASSIGNING, not INTO: from v740 a table expression in a read position addresses the
|
|
78720
|
+
// row rather than copying it, so "REF #( tab[ i ]-comp )" and "ASSIGN tab[ i ]-comp"
|
|
78721
|
+
// hand back an address INTO a work area would not preserve. The write path
|
|
78722
|
+
// (moveWithTableTarget) already lowers to ASSIGNING for the same reason.
|
|
78723
|
+
const uniqueName = this.uniqueName(high.getFirstToken().getStart(), lowFile.getFilename(), highSyntax, true);
|
|
78690
78724
|
const tabixBackup = this.uniqueName(high.getFirstToken().getStart(), lowFile.getFilename(), highSyntax);
|
|
78691
78725
|
const indentation = " ".repeat(high.getFirstToken().getStart().getCol() - 1);
|
|
78692
78726
|
const firstToken = high.getFirstToken();
|
|
78693
78727
|
// note that the tabix restore should be done before throwing the exception
|
|
78694
|
-
const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, firstToken.getStart(), `
|
|
78728
|
+
const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, firstToken.getStart(), `FIELD-SYMBOLS ${uniqueName} LIKE LINE OF ${pre}.
|
|
78695
78729
|
${indentation}DATA ${tabixBackup} LIKE sy-tabix.
|
|
78696
78730
|
${indentation}${tabixBackup} = sy-tabix.
|
|
78697
|
-
${indentation}READ TABLE ${pre} ${condition}
|
|
78731
|
+
${indentation}READ TABLE ${pre} ${condition}ASSIGNING ${uniqueName}.
|
|
78698
78732
|
${indentation}sy-tabix = ${tabixBackup}.
|
|
78699
78733
|
${indentation}IF sy-subrc <> 0.
|
|
78700
78734
|
${indentation} RAISE EXCEPTION TYPE cx_sy_itab_line_not_found.
|
|
@@ -79448,8 +79482,7 @@ CONSTANTS: BEGIN OF ${structureName},\n`;
|
|
|
79448
79482
|
if (index === undefined) {
|
|
79449
79483
|
return undefined;
|
|
79450
79484
|
}
|
|
79451
|
-
|
|
79452
|
-
uniqueName = `<${uniqueName}>`;
|
|
79485
|
+
const uniqueName = this.uniqueName(high.getFirstToken().getStart(), lowFile.getFilename(), highSyntax, true);
|
|
79453
79486
|
const tName = target.concatTokens().split("[")[0];
|
|
79454
79487
|
const condition = this.tableCondition(tableExpression);
|
|
79455
79488
|
const tabixBackup = this.uniqueName(high.getFirstToken().getStart(), lowFile.getFilename(), highSyntax);
|
|
@@ -80461,12 +80494,16 @@ ${indentation} output = ${uniqueName}.\n`;
|
|
|
80461
80494
|
}
|
|
80462
80495
|
return undefined;
|
|
80463
80496
|
}
|
|
80464
|
-
|
|
80497
|
+
/** a FIELD-SYMBOLS declaration is known to the scope under its bracketed spelling, so
|
|
80498
|
+
* the collision check has to use that spelling too - otherwise a second outline in the
|
|
80499
|
+
* same method is handed a name that is already taken and the result does not compile */
|
|
80500
|
+
uniqueName(position, filename, highSyntax, fieldSymbol = false) {
|
|
80501
|
+
const decorate = (name) => fieldSymbol === true ? `<${name}>` : name;
|
|
80465
80502
|
const spag = highSyntax.spaghetti.lookupPosition(position, filename);
|
|
80466
80503
|
if (spag === undefined) {
|
|
80467
80504
|
const name = "temprr" + this.counter;
|
|
80468
80505
|
this.counter++;
|
|
80469
|
-
return name;
|
|
80506
|
+
return decorate(name);
|
|
80470
80507
|
}
|
|
80471
80508
|
let postfix = "";
|
|
80472
80509
|
if (spag.getIdentifier().stype === _scope_type_1.ScopeType.ClassDefinition) {
|
|
@@ -80475,7 +80512,7 @@ ${indentation} output = ${uniqueName}.\n`;
|
|
|
80475
80512
|
postfix = "_" + hash.substring(0, 10);
|
|
80476
80513
|
}
|
|
80477
80514
|
while (true) {
|
|
80478
|
-
const name = "temp" + this.counter + postfix;
|
|
80515
|
+
const name = decorate("temp" + this.counter + postfix);
|
|
80479
80516
|
const exists = this.existsRecursive(spag, name);
|
|
80480
80517
|
this.counter++;
|
|
80481
80518
|
if (exists === false) {
|
|
@@ -84957,6 +84994,7 @@ __exportStar(__webpack_require__(/*! ./use_line_exists */ "../core/build/src/rul
|
|
|
84957
84994
|
__exportStar(__webpack_require__(/*! ./use_new */ "../core/build/src/rules/use_new.js"), exports);
|
|
84958
84995
|
__exportStar(__webpack_require__(/*! ./when_others_last */ "../core/build/src/rules/when_others_last.js"), exports);
|
|
84959
84996
|
__exportStar(__webpack_require__(/*! ./whitespace_end */ "../core/build/src/rules/whitespace_end.js"), exports);
|
|
84997
|
+
__exportStar(__webpack_require__(/*! ./wrong_abapdoc_position */ "../core/build/src/rules/wrong_abapdoc_position.js"), exports);
|
|
84960
84998
|
__exportStar(__webpack_require__(/*! ./xml_consistency */ "../core/build/src/rules/xml_consistency.js"), exports);
|
|
84961
84999
|
__exportStar(__webpack_require__(/*! ./no_exclamation_escape */ "../core/build/src/rules/no_exclamation_escape.js"), exports);
|
|
84962
85000
|
__exportStar(__webpack_require__(/*! ./xml_bom */ "../core/build/src/rules/xml_bom.js"), exports);
|
|
@@ -100439,6 +100477,178 @@ exports.WhitespaceEnd = WhitespaceEnd;
|
|
|
100439
100477
|
|
|
100440
100478
|
/***/ },
|
|
100441
100479
|
|
|
100480
|
+
/***/ "../core/build/src/rules/wrong_abapdoc_position.js"
|
|
100481
|
+
/*!*********************************************************!*\
|
|
100482
|
+
!*** ../core/build/src/rules/wrong_abapdoc_position.js ***!
|
|
100483
|
+
\*********************************************************/
|
|
100484
|
+
(__unused_webpack_module, exports, __webpack_require__) {
|
|
100485
|
+
|
|
100486
|
+
"use strict";
|
|
100487
|
+
|
|
100488
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
100489
|
+
if (k2 === undefined) k2 = k;
|
|
100490
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
100491
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
100492
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
100493
|
+
}
|
|
100494
|
+
Object.defineProperty(o, k2, desc);
|
|
100495
|
+
}) : (function(o, m, k, k2) {
|
|
100496
|
+
if (k2 === undefined) k2 = k;
|
|
100497
|
+
o[k2] = m[k];
|
|
100498
|
+
}));
|
|
100499
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
100500
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
100501
|
+
}) : function(o, v) {
|
|
100502
|
+
o["default"] = v;
|
|
100503
|
+
});
|
|
100504
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
100505
|
+
var ownKeys = function(o) {
|
|
100506
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
100507
|
+
var ar = [];
|
|
100508
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
100509
|
+
return ar;
|
|
100510
|
+
};
|
|
100511
|
+
return ownKeys(o);
|
|
100512
|
+
};
|
|
100513
|
+
return function (mod) {
|
|
100514
|
+
if (mod && mod.__esModule) return mod;
|
|
100515
|
+
var result = {};
|
|
100516
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
100517
|
+
__setModuleDefault(result, mod);
|
|
100518
|
+
return result;
|
|
100519
|
+
};
|
|
100520
|
+
})();
|
|
100521
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
100522
|
+
exports.WrongAbapdocPosition = exports.WrongAbapdocPositionConf = void 0;
|
|
100523
|
+
const Statements = __importStar(__webpack_require__(/*! ../abap/2_statements/statements */ "../core/build/src/abap/2_statements/statements/index.js"));
|
|
100524
|
+
const issue_1 = __webpack_require__(/*! ../issue */ "../core/build/src/issue.js");
|
|
100525
|
+
const _abap_rule_1 = __webpack_require__(/*! ./_abap_rule */ "../core/build/src/rules/_abap_rule.js");
|
|
100526
|
+
const _basic_rule_config_1 = __webpack_require__(/*! ./_basic_rule_config */ "../core/build/src/rules/_basic_rule_config.js");
|
|
100527
|
+
const _irule_1 = __webpack_require__(/*! ./_irule */ "../core/build/src/rules/_irule.js");
|
|
100528
|
+
const _statement_1 = __webpack_require__(/*! ../abap/2_statements/statements/_statement */ "../core/build/src/abap/2_statements/statements/_statement.js");
|
|
100529
|
+
class WrongAbapdocPositionConf extends _basic_rule_config_1.BasicRuleConfig {
|
|
100530
|
+
}
|
|
100531
|
+
exports.WrongAbapdocPositionConf = WrongAbapdocPositionConf;
|
|
100532
|
+
class WrongAbapdocPosition extends _abap_rule_1.ABAPRule {
|
|
100533
|
+
constructor() {
|
|
100534
|
+
super(...arguments);
|
|
100535
|
+
this.conf = new WrongAbapdocPositionConf();
|
|
100536
|
+
}
|
|
100537
|
+
getMetadata() {
|
|
100538
|
+
return {
|
|
100539
|
+
key: "wrong_abapdoc_position",
|
|
100540
|
+
title: "Wrong ABAP Doc position",
|
|
100541
|
+
shortDescription: `ABAP Doc must be placed directly in front of the declaration it documents.`,
|
|
100542
|
+
extendedInformation: `ABAP Doc documents the single declaration following it, an ABAP Doc block placed
|
|
100543
|
+
elsewhere is silently ignored, leaving the declaration undocumented.
|
|
100544
|
+
|
|
100545
|
+
The following positions are reported,
|
|
100546
|
+
* in front of a chained keyword, ie. before "CONSTANTS:" instead of after the colon,
|
|
100547
|
+
* in the middle of a statement, ie. between the parameters of a METHODS definition,
|
|
100548
|
+
* directly in front of ENDCLASS, ENDINTERFACE or a SECTION statement.
|
|
100549
|
+
|
|
100550
|
+
Only checks ABAP Doc inside class definitions and interfaces.`,
|
|
100551
|
+
tags: [_irule_1.RuleTag.SingleFile],
|
|
100552
|
+
badExample: `CLASS zcl_foo DEFINITION PUBLIC.
|
|
100553
|
+
PUBLIC SECTION.
|
|
100554
|
+
"! Navigation modes
|
|
100555
|
+
CONSTANTS:
|
|
100556
|
+
BEGIN OF cs_nav_mode,
|
|
100557
|
+
back TYPE i VALUE 1,
|
|
100558
|
+
END OF cs_nav_mode.
|
|
100559
|
+
ENDCLASS.`,
|
|
100560
|
+
goodExample: `CLASS zcl_foo DEFINITION PUBLIC.
|
|
100561
|
+
PUBLIC SECTION.
|
|
100562
|
+
CONSTANTS:
|
|
100563
|
+
"! Navigation modes
|
|
100564
|
+
BEGIN OF cs_nav_mode,
|
|
100565
|
+
back TYPE i VALUE 1,
|
|
100566
|
+
END OF cs_nav_mode.
|
|
100567
|
+
ENDCLASS.`,
|
|
100568
|
+
};
|
|
100569
|
+
}
|
|
100570
|
+
getConfig() {
|
|
100571
|
+
return this.conf;
|
|
100572
|
+
}
|
|
100573
|
+
setConfig(conf) {
|
|
100574
|
+
this.conf = conf;
|
|
100575
|
+
}
|
|
100576
|
+
runParsed(file) {
|
|
100577
|
+
const issues = [];
|
|
100578
|
+
const statements = file.getStatements();
|
|
100579
|
+
let definition = false;
|
|
100580
|
+
for (let i = 0; i < statements.length; i++) {
|
|
100581
|
+
const statement = statements[i];
|
|
100582
|
+
const type = statement.get();
|
|
100583
|
+
if (type instanceof Statements.ClassDefinition || type instanceof Statements.Interface) {
|
|
100584
|
+
definition = true;
|
|
100585
|
+
continue;
|
|
100586
|
+
}
|
|
100587
|
+
else if (type instanceof Statements.EndClass || type instanceof Statements.EndInterface) {
|
|
100588
|
+
definition = false;
|
|
100589
|
+
continue;
|
|
100590
|
+
}
|
|
100591
|
+
else if (definition === false || this.isAbapdoc(statement) === false) {
|
|
100592
|
+
continue;
|
|
100593
|
+
}
|
|
100594
|
+
else if (this.isAbapdoc(statements[i - 1]) === true
|
|
100595
|
+
&& statements[i - 1].getStart().getRow() + 1 === statement.getStart().getRow()) {
|
|
100596
|
+
continue; // only report the first row of each block
|
|
100597
|
+
}
|
|
100598
|
+
let next = undefined;
|
|
100599
|
+
for (let j = i + 1; j < statements.length; j++) {
|
|
100600
|
+
if (statements[j].get() instanceof _statement_1.Comment) {
|
|
100601
|
+
continue;
|
|
100602
|
+
}
|
|
100603
|
+
next = statements[j];
|
|
100604
|
+
break;
|
|
100605
|
+
}
|
|
100606
|
+
if (next === undefined) {
|
|
100607
|
+
continue;
|
|
100608
|
+
}
|
|
100609
|
+
const message = this.check(statement, next);
|
|
100610
|
+
if (message !== undefined) {
|
|
100611
|
+
issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity));
|
|
100612
|
+
}
|
|
100613
|
+
}
|
|
100614
|
+
return issues;
|
|
100615
|
+
}
|
|
100616
|
+
isAbapdoc(statement) {
|
|
100617
|
+
return (statement === null || statement === void 0 ? void 0 : statement.get()) instanceof _statement_1.Comment
|
|
100618
|
+
&& statement.getFirstToken().getStr().startsWith(`"!`);
|
|
100619
|
+
}
|
|
100620
|
+
check(abapdoc, next) {
|
|
100621
|
+
const type = next.get();
|
|
100622
|
+
if (type instanceof Statements.EndClass
|
|
100623
|
+
|| type instanceof Statements.EndInterface
|
|
100624
|
+
|| type instanceof Statements.Public
|
|
100625
|
+
|| type instanceof Statements.Protected
|
|
100626
|
+
|| type instanceof Statements.Private) {
|
|
100627
|
+
return "ABAP Doc does not document anything, move or delete it";
|
|
100628
|
+
}
|
|
100629
|
+
const position = abapdoc.getStart();
|
|
100630
|
+
const colon = next.getColon();
|
|
100631
|
+
if (colon === undefined) {
|
|
100632
|
+
if (position.isAfter(next.getStart()) === true) {
|
|
100633
|
+
return "ABAP Doc inside statement, move it in front of the statement";
|
|
100634
|
+
}
|
|
100635
|
+
return undefined;
|
|
100636
|
+
}
|
|
100637
|
+
if (position.isBefore(colon.getStart()) === true) {
|
|
100638
|
+
return "ABAP Doc in front of chained statement, move it after the colon";
|
|
100639
|
+
}
|
|
100640
|
+
const member = next.getTokens().find(t => t.getStart().isAfter(colon.getStart()));
|
|
100641
|
+
if (member !== undefined && position.isAfter(member.getStart()) === true) {
|
|
100642
|
+
return "ABAP Doc inside statement, move it in front of the chained declaration";
|
|
100643
|
+
}
|
|
100644
|
+
return undefined;
|
|
100645
|
+
}
|
|
100646
|
+
}
|
|
100647
|
+
exports.WrongAbapdocPosition = WrongAbapdocPosition;
|
|
100648
|
+
//# sourceMappingURL=wrong_abapdoc_position.js.map
|
|
100649
|
+
|
|
100650
|
+
/***/ },
|
|
100651
|
+
|
|
100442
100652
|
/***/ "../core/build/src/rules/xml_bom.js"
|
|
100443
100653
|
/*!******************************************!*\
|
|
100444
100654
|
!*** ../core/build/src/rules/xml_bom.js ***!
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abaplint/cli",
|
|
3
|
-
"version": "2.120.
|
|
3
|
+
"version": "2.120.52",
|
|
4
4
|
"description": "abaplint - Command Line Interface",
|
|
5
5
|
"funding": "https://github.com/sponsors/larshp",
|
|
6
6
|
"bin": {
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
},
|
|
40
40
|
"homepage": "https://abaplint.org",
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@abaplint/core": "^2.120.
|
|
42
|
+
"@abaplint/core": "^2.120.52",
|
|
43
43
|
"@types/chai": "^4.3.20",
|
|
44
44
|
"@types/minimist": "^1.2.5",
|
|
45
45
|
"@types/mocha": "^10.0.10",
|