@abaplint/cli 2.119.37 → 2.119.39
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 +91 -24
- package/package.json +2 -2
package/build/cli.js
CHANGED
|
@@ -26933,16 +26933,16 @@ class BasicTypes {
|
|
|
26933
26933
|
options.primaryKey.type = basic_1.TableAccessType.standard;
|
|
26934
26934
|
return new Types.TableType(structure, options);
|
|
26935
26935
|
}
|
|
26936
|
-
else if (typename && (text
|
|
26937
|
-
|| text.startsWith("TYPE TABLE FOR READ ")
|
|
26938
|
-
|| text.startsWith("TYPE TABLE FOR DELETE ")
|
|
26939
|
-
|| text.startsWith("TYPE TABLE FOR UPDATE "))) {
|
|
26936
|
+
else if (typename && this.isRAPTableFor(text)) {
|
|
26940
26937
|
const name = typename.concatTokens();
|
|
26941
26938
|
const ddlsName = this.getRAPBaseEntityName(name);
|
|
26942
26939
|
const type = (_d = this.input.scope.getDDIC().lookupDDLS(ddlsName)) === null || _d === void 0 ? void 0 : _d.type;
|
|
26943
26940
|
if (type) {
|
|
26944
26941
|
return new Types.TableType(basic_1.VoidType.get("RAP-TODO"), options);
|
|
26945
26942
|
}
|
|
26943
|
+
else if (this.isRAPDerivedEntityName(name)) {
|
|
26944
|
+
return Types.VoidType.get(name);
|
|
26945
|
+
}
|
|
26946
26946
|
else if (this.input.scope.getDDIC().inErrorNamespace(ddlsName)) {
|
|
26947
26947
|
return new Types.UnknownType(`DDLS ${ddlsName} not found`);
|
|
26948
26948
|
}
|
|
@@ -26954,7 +26954,7 @@ class BasicTypes {
|
|
|
26954
26954
|
return this.parseType(node, name);
|
|
26955
26955
|
}
|
|
26956
26956
|
parseType(node, qualifiedName) {
|
|
26957
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
26957
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
26958
26958
|
const typeName = node.findFirstExpression(Expressions.TypeName);
|
|
26959
26959
|
let text = (_a = node.findFirstExpression(Expressions.Type)) === null || _a === void 0 ? void 0 : _a.concatTokens().toUpperCase();
|
|
26960
26960
|
if (text === undefined) {
|
|
@@ -26967,7 +26967,10 @@ class BasicTypes {
|
|
|
26967
26967
|
}
|
|
26968
26968
|
}
|
|
26969
26969
|
if (text === undefined) {
|
|
26970
|
-
text = (_d = node.findFirstExpression(Expressions.
|
|
26970
|
+
text = (_d = node.findFirstExpression(Expressions.TypeStructure)) === null || _d === void 0 ? void 0 : _d.concatTokens().toUpperCase();
|
|
26971
|
+
}
|
|
26972
|
+
if (text === undefined) {
|
|
26973
|
+
text = (_e = node.findFirstExpression(Expressions.FormParamType)) === null || _e === void 0 ? void 0 : _e.concatTokens().toUpperCase();
|
|
26971
26974
|
}
|
|
26972
26975
|
if (text === undefined
|
|
26973
26976
|
&& node.get() instanceof Statements.Parameter
|
|
@@ -26978,8 +26981,11 @@ class BasicTypes {
|
|
|
26978
26981
|
text = "TYPE";
|
|
26979
26982
|
}
|
|
26980
26983
|
let found = undefined;
|
|
26981
|
-
if (
|
|
26982
|
-
|
|
26984
|
+
if (this.isRAPTypeStructure(text)) {
|
|
26985
|
+
return Types.VoidType.get((_f = node.findFirstExpression(Expressions.TypeStructure)) === null || _f === void 0 ? void 0 : _f.concatTokens());
|
|
26986
|
+
}
|
|
26987
|
+
else if (text.startsWith("LIKE LINE OF ")) {
|
|
26988
|
+
const name = (_g = node.findFirstExpression(Expressions.FieldChain)) === null || _g === void 0 ? void 0 : _g.concatTokens();
|
|
26983
26989
|
let e = node.findFirstExpression(Expressions.Type);
|
|
26984
26990
|
if (e === undefined) {
|
|
26985
26991
|
e = node.findFirstExpression(Expressions.FormParamType);
|
|
@@ -27002,7 +27008,7 @@ class BasicTypes {
|
|
|
27002
27008
|
}
|
|
27003
27009
|
}
|
|
27004
27010
|
else if (text.startsWith("LIKE REF TO ")) {
|
|
27005
|
-
const name = (
|
|
27011
|
+
const name = (_h = node.findFirstExpression(Expressions.FieldChain)) === null || _h === void 0 ? void 0 : _h.concatTokens();
|
|
27006
27012
|
const type = this.resolveLikeName(node.findFirstExpression(Expressions.Type), false);
|
|
27007
27013
|
if (type === undefined) {
|
|
27008
27014
|
return new Types.UnknownType("Type error, could not resolve \"" + name + "\", parseType");
|
|
@@ -27093,7 +27099,7 @@ class BasicTypes {
|
|
|
27093
27099
|
}
|
|
27094
27100
|
}
|
|
27095
27101
|
if (text.includes(" WITH INDICATORS ")) {
|
|
27096
|
-
const componentName = (
|
|
27102
|
+
const componentName = (_k = (_j = node.findFirstExpression(Expressions.Type)) === null || _j === void 0 ? void 0 : _j.findDirectExpression(Expressions.ComponentName)) === null || _k === void 0 ? void 0 : _k.concatTokens().toUpperCase();
|
|
27097
27103
|
if (componentName === undefined) {
|
|
27098
27104
|
throw new Error("parseType, componentName expected");
|
|
27099
27105
|
}
|
|
@@ -27119,12 +27125,38 @@ class BasicTypes {
|
|
|
27119
27125
|
getRAPBaseEntityName(name) {
|
|
27120
27126
|
const association = name.indexOf("\\_");
|
|
27121
27127
|
const path = name.indexOf("\\\\");
|
|
27122
|
-
|
|
27128
|
+
const action = name.indexOf("~");
|
|
27129
|
+
if (association === -1 && path === -1 && action === -1) {
|
|
27123
27130
|
return name;
|
|
27124
27131
|
}
|
|
27125
|
-
const
|
|
27132
|
+
const candidates = [association, path, action].filter(i => i !== -1);
|
|
27133
|
+
const splitAt = Math.min(...candidates);
|
|
27126
27134
|
return name.substring(0, splitAt);
|
|
27127
27135
|
}
|
|
27136
|
+
isRAPDerivedEntityName(name) {
|
|
27137
|
+
return name.includes("\\") || name.includes("~");
|
|
27138
|
+
}
|
|
27139
|
+
isRAPTableFor(text) {
|
|
27140
|
+
return text.startsWith("TYPE TABLE FOR ACTION IMPORT ")
|
|
27141
|
+
|| text.startsWith("TYPE TABLE FOR ACTION RESULT ")
|
|
27142
|
+
|| text.startsWith("TYPE TABLE FOR CREATE ")
|
|
27143
|
+
|| text.startsWith("TYPE TABLE FOR DELETE ")
|
|
27144
|
+
|| text.startsWith("TYPE TABLE FOR DETERMINATION ")
|
|
27145
|
+
|| text.startsWith("TYPE TABLE FOR EVENT ")
|
|
27146
|
+
|| text.startsWith("TYPE TABLE FOR FAILED ")
|
|
27147
|
+
|| text.startsWith("TYPE TABLE FOR FAILED EARLY ")
|
|
27148
|
+
|| text.startsWith("TYPE TABLE FOR LOCK ")
|
|
27149
|
+
|| text.startsWith("TYPE TABLE FOR READ ")
|
|
27150
|
+
|| text.startsWith("TYPE TABLE FOR READ IMPORT ")
|
|
27151
|
+
|| text.startsWith("TYPE TABLE FOR READ RESULT ")
|
|
27152
|
+
|| text.startsWith("TYPE TABLE FOR REPORTED EARLY ")
|
|
27153
|
+
|| text.startsWith("TYPE TABLE FOR UPDATE ");
|
|
27154
|
+
}
|
|
27155
|
+
isRAPTypeStructure(text) {
|
|
27156
|
+
return text.startsWith("TYPE STRUCTURE FOR ")
|
|
27157
|
+
|| text.startsWith("TYPE RESPONSE FOR ")
|
|
27158
|
+
|| text.startsWith("TYPE REQUEST FOR CHANGE ");
|
|
27159
|
+
}
|
|
27128
27160
|
// todo, rewrite this method
|
|
27129
27161
|
resolveTypeChain(expr) {
|
|
27130
27162
|
var _a, _b, _c, _d;
|
|
@@ -37383,6 +37415,7 @@ const source_1 = __webpack_require__(/*! ../expressions/source */ "../core/build
|
|
|
37383
37415
|
const component_compare_1 = __webpack_require__(/*! ../expressions/component_compare */ "../core/build/src/abap/5_syntax/expressions/component_compare.js");
|
|
37384
37416
|
const component_cond_1 = __webpack_require__(/*! ../expressions/component_cond */ "../core/build/src/abap/5_syntax/expressions/component_cond.js");
|
|
37385
37417
|
const basic_1 = __webpack_require__(/*! ../../types/basic */ "../core/build/src/abap/types/basic/index.js");
|
|
37418
|
+
const _syntax_input_1 = __webpack_require__(/*! ../_syntax_input */ "../core/build/src/abap/5_syntax/_syntax_input.js");
|
|
37386
37419
|
class DeleteInternal {
|
|
37387
37420
|
runSyntax(node, input) {
|
|
37388
37421
|
var _a;
|
|
@@ -37393,7 +37426,8 @@ class DeleteInternal {
|
|
|
37393
37426
|
const target = node.findDirectExpression(Expressions.Target);
|
|
37394
37427
|
if (target) {
|
|
37395
37428
|
let tabl = undefined;
|
|
37396
|
-
|
|
37429
|
+
const localVariable = input.scope.findVariable(target.concatTokens());
|
|
37430
|
+
if (localVariable === undefined && node.getChildren().length === 5 && node.getChildren()[2].concatTokens().toUpperCase() === "FROM") {
|
|
37397
37431
|
// it might be a database table
|
|
37398
37432
|
tabl = (_a = input.scope.getDDIC()) === null || _a === void 0 ? void 0 : _a.lookupTableOrView(target.concatTokens());
|
|
37399
37433
|
if (tabl) {
|
|
@@ -37402,6 +37436,14 @@ class DeleteInternal {
|
|
|
37402
37436
|
}
|
|
37403
37437
|
if (tabl === undefined) {
|
|
37404
37438
|
targetType = target_1.Target.runSyntax(target, input);
|
|
37439
|
+
if (node.findDirectTokenByText("TABLE") === undefined
|
|
37440
|
+
&& node.findDirectTokenByText("FROM")
|
|
37441
|
+
&& targetType instanceof basic_1.TableType
|
|
37442
|
+
&& targetType.getAccessType() === basic_1.TableAccessType.hashed) {
|
|
37443
|
+
const message = "Implicit or explicit index operation on hashed table is not possible";
|
|
37444
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
|
|
37445
|
+
return;
|
|
37446
|
+
}
|
|
37405
37447
|
if (targetType instanceof basic_1.TableType) {
|
|
37406
37448
|
targetType = targetType.getRowType();
|
|
37407
37449
|
}
|
|
@@ -45846,6 +45888,10 @@ class SyntaxLogic {
|
|
|
45846
45888
|
this.scope.addList(values);
|
|
45847
45889
|
return true;
|
|
45848
45890
|
}
|
|
45891
|
+
else if (stru instanceof Structures.TestInjection) {
|
|
45892
|
+
// todo: skipped for now
|
|
45893
|
+
return true;
|
|
45894
|
+
}
|
|
45849
45895
|
return false;
|
|
45850
45896
|
}
|
|
45851
45897
|
updateScopeStatement(node) {
|
|
@@ -66531,7 +66577,7 @@ class Registry {
|
|
|
66531
66577
|
}
|
|
66532
66578
|
static abaplintVersion() {
|
|
66533
66579
|
// magic, see build script "version.js"
|
|
66534
|
-
return "2.119.
|
|
66580
|
+
return "2.119.39";
|
|
66535
66581
|
}
|
|
66536
66582
|
getDDICReferences() {
|
|
66537
66583
|
return this.ddicReferences;
|
|
@@ -89398,6 +89444,9 @@ class SelectionScreenTextsMissing {
|
|
|
89398
89444
|
key: "selection_screen_texts_missing",
|
|
89399
89445
|
title: "Selection screen texts missing",
|
|
89400
89446
|
shortDescription: `Checks that selection screen parameters and select-options have selection texts`,
|
|
89447
|
+
extendedInformation: `Excludes parameters and select-options that:
|
|
89448
|
+
* are inside a "SELECTION-SCREEN BEGIN OF LINE" block
|
|
89449
|
+
* have the addition "NO-DISPLAY"`,
|
|
89401
89450
|
};
|
|
89402
89451
|
}
|
|
89403
89452
|
getConfig() {
|
|
@@ -89423,7 +89472,7 @@ class SelectionScreenTextsMissing {
|
|
|
89423
89472
|
this.checkFile(obj.getMainABAPFile(), selTexts, output, checked);
|
|
89424
89473
|
return output;
|
|
89425
89474
|
}
|
|
89426
|
-
checkFile(file, selTexts, output, checked) {
|
|
89475
|
+
checkFile(file, selTexts, output, checked, mainProgName = undefined) {
|
|
89427
89476
|
if (file === undefined) {
|
|
89428
89477
|
return;
|
|
89429
89478
|
}
|
|
@@ -89431,26 +89480,44 @@ class SelectionScreenTextsMissing {
|
|
|
89431
89480
|
return;
|
|
89432
89481
|
}
|
|
89433
89482
|
checked.add(file.getFilename());
|
|
89483
|
+
let inLine = false;
|
|
89434
89484
|
for (const stat of file.getStatements()) {
|
|
89435
89485
|
const s = stat.get();
|
|
89436
|
-
if (s instanceof statements_1.
|
|
89437
|
-
const
|
|
89438
|
-
if (
|
|
89439
|
-
|
|
89440
|
-
if (selTexts[fieldName] === undefined) {
|
|
89441
|
-
output.push(issue_1.Issue.atToken(file, fieldNode.getFirstToken(), `Selection text missing for "${fieldName}"`, this.getMetadata().key, this.conf.severity));
|
|
89442
|
-
}
|
|
89486
|
+
if (s instanceof statements_1.SelectionScreen) {
|
|
89487
|
+
const tokens = stat.concatTokens().toUpperCase();
|
|
89488
|
+
if (tokens.includes("BEGIN OF LINE")) {
|
|
89489
|
+
inLine = true;
|
|
89443
89490
|
}
|
|
89491
|
+
else if (tokens.includes("END OF LINE")) {
|
|
89492
|
+
// known issue: doesn't support BEGIN and END OF LINE span across several includes (not seen a lot in the wild)
|
|
89493
|
+
inLine = false;
|
|
89494
|
+
}
|
|
89495
|
+
continue;
|
|
89444
89496
|
}
|
|
89445
|
-
|
|
89497
|
+
if (s instanceof statements_1.Include) {
|
|
89446
89498
|
const nameNode = stat.findFirstExpression(expressions_1.IncludeName);
|
|
89447
89499
|
if (nameNode) {
|
|
89448
89500
|
const inclName = nameNode.getFirstToken().getStr().toUpperCase();
|
|
89449
89501
|
const inclObj = this.reg.getObject("PROG", inclName);
|
|
89450
89502
|
if (inclObj) {
|
|
89451
|
-
this.checkFile(inclObj.getMainABAPFile(), selTexts, output, checked);
|
|
89503
|
+
this.checkFile(inclObj.getMainABAPFile(), selTexts, output, checked, mainProgName !== null && mainProgName !== void 0 ? mainProgName : file.getFilename());
|
|
89452
89504
|
}
|
|
89453
89505
|
}
|
|
89506
|
+
continue;
|
|
89507
|
+
}
|
|
89508
|
+
if (inLine || !(s instanceof statements_1.Parameter || s instanceof statements_1.SelectOption)) {
|
|
89509
|
+
continue;
|
|
89510
|
+
}
|
|
89511
|
+
if (stat.concatTokens().toUpperCase().includes("NO-DISPLAY")) {
|
|
89512
|
+
continue;
|
|
89513
|
+
}
|
|
89514
|
+
const fieldNode = stat.findFirstExpression(expressions_1.FieldSub);
|
|
89515
|
+
if (fieldNode) {
|
|
89516
|
+
const fieldName = fieldNode.getFirstToken().getStr().toUpperCase();
|
|
89517
|
+
if (selTexts[fieldName] === undefined) {
|
|
89518
|
+
const suffix = mainProgName ? `, ${mainProgName}` : ``;
|
|
89519
|
+
output.push(issue_1.Issue.atToken(file, fieldNode.getFirstToken(), `Selection text missing for "${fieldName}"${suffix}`, this.getMetadata().key, this.conf.severity));
|
|
89520
|
+
}
|
|
89454
89521
|
}
|
|
89455
89522
|
}
|
|
89456
89523
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abaplint/cli",
|
|
3
|
-
"version": "2.119.
|
|
3
|
+
"version": "2.119.39",
|
|
4
4
|
"description": "abaplint - Command Line Interface",
|
|
5
5
|
"funding": "https://github.com/sponsors/larshp",
|
|
6
6
|
"bin": {
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
},
|
|
39
39
|
"homepage": "https://abaplint.org",
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@abaplint/core": "^2.119.
|
|
41
|
+
"@abaplint/core": "^2.119.39",
|
|
42
42
|
"@types/chai": "^4.3.20",
|
|
43
43
|
"@types/minimist": "^1.2.5",
|
|
44
44
|
"@types/mocha": "^10.0.10",
|