@abaplint/core 2.90.11 → 2.91.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/abaplint.d.ts +1 -0
- package/build/src/abap/5_syntax/_type_utils.js +2 -0
- package/build/src/cds/expressions/cds_with_parameters.js +1 -1
- package/build/src/objects/data_definition.js +4 -0
- package/build/src/objects/table.js +7 -0
- package/build/src/registry.js +1 -1
- package/build/src/rules/cds_legacy_view.js +63 -0
- package/build/src/rules/cds_parser_error.js +2 -2
- package/build/src/rules/downport.js +3 -8
- package/build/src/rules/index.js +2 -0
- package/build/src/rules/superfluous_value.js +73 -0
- package/build/src/rules/unnecessary_pragma.js +25 -3
- package/package.json +1 -1
package/build/abaplint.d.ts
CHANGED
|
@@ -1262,6 +1262,7 @@ declare class DataDefinition extends AbstractObject {
|
|
|
1262
1262
|
findSourceFile(): IFile | undefined;
|
|
1263
1263
|
hasParserError(): boolean | undefined;
|
|
1264
1264
|
parse(): IParseResult;
|
|
1265
|
+
getTree(): ExpressionNode | undefined;
|
|
1265
1266
|
private findSQLViewName;
|
|
1266
1267
|
private findFieldNames;
|
|
1267
1268
|
private findSourcesAndRelations;
|
|
@@ -22,6 +22,7 @@ class TypeUtils {
|
|
|
22
22
|
else if (type instanceof basic_1.StringType
|
|
23
23
|
|| type instanceof basic_1.AnyType
|
|
24
24
|
|| type instanceof basic_1.CharacterType
|
|
25
|
+
|| type instanceof basic_1.SimpleType
|
|
25
26
|
|| type instanceof basic_1.CLikeType
|
|
26
27
|
|| type instanceof basic_1.DateType
|
|
27
28
|
|| type instanceof basic_1.CSequenceType
|
|
@@ -55,6 +56,7 @@ class TypeUtils {
|
|
|
55
56
|
|| type instanceof basic_1.UnknownType
|
|
56
57
|
|| type instanceof basic_1.NumericType
|
|
57
58
|
|| type instanceof basic_1.IntegerType
|
|
59
|
+
|| type instanceof basic_1.SimpleType
|
|
58
60
|
|| type instanceof basic_1.FloatType
|
|
59
61
|
|| type instanceof basic_1.FloatingPointType
|
|
60
62
|
|| type instanceof basic_1.DecFloatType
|
|
@@ -6,7 +6,7 @@ const combi_1 = require("../../abap/2_statements/combi");
|
|
|
6
6
|
class CDSWithParameters extends combi_1.Expression {
|
|
7
7
|
getRunnable() {
|
|
8
8
|
const param = (0, combi_1.seq)(_1.CDSName, ":", _1.CDSType);
|
|
9
|
-
return (0, combi_1.seq)("
|
|
9
|
+
return (0, combi_1.seq)("WITH PARAMETERS", param, (0, combi_1.star)((0, combi_1.seq)(",", param)));
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
exports.CDSWithParameters = CDSWithParameters;
|
|
@@ -85,6 +85,10 @@ class DataDefinition extends _abstract_object_1.AbstractObject {
|
|
|
85
85
|
this.dirty = false;
|
|
86
86
|
return { updated: true, runtime: Date.now() - start };
|
|
87
87
|
}
|
|
88
|
+
getTree() {
|
|
89
|
+
var _a;
|
|
90
|
+
return (_a = this.parsedData) === null || _a === void 0 ? void 0 : _a.tree;
|
|
91
|
+
}
|
|
88
92
|
//////////
|
|
89
93
|
findSQLViewName() {
|
|
90
94
|
var _a;
|
|
@@ -208,6 +208,12 @@ class Table extends _abstract_object_1.AbstractObject {
|
|
|
208
208
|
type: new Types.UnknownType("Table " + this.getName() + ", unknown component type \"" + comptype + "\"")
|
|
209
209
|
});
|
|
210
210
|
}
|
|
211
|
+
if (field.CHECKTABLE) {
|
|
212
|
+
const lookup = ddic.lookupTableOrView(field.CHECKTABLE);
|
|
213
|
+
if (lookup.object) {
|
|
214
|
+
references.push({ object: lookup.object });
|
|
215
|
+
}
|
|
216
|
+
}
|
|
211
217
|
}
|
|
212
218
|
if (components.length === 0) {
|
|
213
219
|
return new Types.UnknownType("Table/Structure " + this.getName() + " does not contain any components");
|
|
@@ -266,6 +272,7 @@ class Table extends _abstract_object_1.AbstractObject {
|
|
|
266
272
|
DECIMALS: field.DECIMALS,
|
|
267
273
|
KEYFLAG: field.KEYFLAG,
|
|
268
274
|
GROUPNAME: field.GROUPNAME,
|
|
275
|
+
CHECKTABLE: field.CHECKTABLE,
|
|
269
276
|
REFTYPE: field.REFTYPE,
|
|
270
277
|
});
|
|
271
278
|
}
|
package/build/src/registry.js
CHANGED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CDSLegacyView = exports.CDSLegacyViewConf = void 0;
|
|
4
|
+
const issue_1 = require("../issue");
|
|
5
|
+
const _irule_1 = require("./_irule");
|
|
6
|
+
const version_1 = require("../version");
|
|
7
|
+
const _basic_rule_config_1 = require("./_basic_rule_config");
|
|
8
|
+
const objects_1 = require("../objects");
|
|
9
|
+
class CDSLegacyViewConf extends _basic_rule_config_1.BasicRuleConfig {
|
|
10
|
+
}
|
|
11
|
+
exports.CDSLegacyViewConf = CDSLegacyViewConf;
|
|
12
|
+
class CDSLegacyView {
|
|
13
|
+
constructor() {
|
|
14
|
+
this.conf = new CDSLegacyViewConf();
|
|
15
|
+
}
|
|
16
|
+
getMetadata() {
|
|
17
|
+
return {
|
|
18
|
+
key: "cds_legacy_view",
|
|
19
|
+
title: "CDS Legacy View",
|
|
20
|
+
shortDescription: `Identify CDS Legacy Views`,
|
|
21
|
+
// eslint-disable-next-line max-len
|
|
22
|
+
extendedInformation: `https://blogs.sap.com/2021/10/16/a-new-generation-of-cds-views-how-to-migrate-your-cds-views-to-cds-view-entities/
|
|
23
|
+
|
|
24
|
+
v755 and up`,
|
|
25
|
+
tags: [_irule_1.RuleTag.SingleFile],
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
getConfig() {
|
|
29
|
+
return this.conf;
|
|
30
|
+
}
|
|
31
|
+
setConfig(conf) {
|
|
32
|
+
this.conf = conf;
|
|
33
|
+
}
|
|
34
|
+
initialize(reg) {
|
|
35
|
+
this.reg = reg;
|
|
36
|
+
return this;
|
|
37
|
+
}
|
|
38
|
+
run(o) {
|
|
39
|
+
const issues = [];
|
|
40
|
+
if (this.reg.getConfig().getVersion() < version_1.Version.v755
|
|
41
|
+
&& this.reg.getConfig().getVersion() !== version_1.Version.Cloud) {
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
if (o.getType() !== "DDLS") {
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
47
|
+
if (o instanceof objects_1.DataDefinition) {
|
|
48
|
+
const tree = o.getTree();
|
|
49
|
+
if (tree === undefined) {
|
|
50
|
+
return []; // parser error
|
|
51
|
+
}
|
|
52
|
+
if (tree.findDirectTokenByText("ENTITY") === undefined) {
|
|
53
|
+
const file = o.findSourceFile();
|
|
54
|
+
if (file) {
|
|
55
|
+
issues.push(issue_1.Issue.atRow(file, 1, "CDS Legacy View", this.getMetadata().key, this.getConfig().severity));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return issues;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
exports.CDSLegacyView = CDSLegacyView;
|
|
63
|
+
//# sourceMappingURL=cds_legacy_view.js.map
|
|
@@ -18,7 +18,7 @@ class CDSParserError {
|
|
|
18
18
|
title: "CDS Parser Error",
|
|
19
19
|
shortDescription: `CDS parsing, experimental`,
|
|
20
20
|
extendedInformation: ``,
|
|
21
|
-
tags: [_irule_1.RuleTag.Syntax
|
|
21
|
+
tags: [_irule_1.RuleTag.Syntax],
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
24
|
getConfig() {
|
|
@@ -36,7 +36,7 @@ class CDSParserError {
|
|
|
36
36
|
const hasError = o.hasParserError();
|
|
37
37
|
const file = o.findSourceFile();
|
|
38
38
|
if (hasError === true && file) {
|
|
39
|
-
issues.push(issue_1.Issue.atRow(file, 1, "CDS Parser error", this.getMetadata().key));
|
|
39
|
+
issues.push(issue_1.Issue.atRow(file, 1, "CDS Parser error", this.getMetadata().key, this.getConfig().severity));
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
return issues;
|
|
@@ -1252,14 +1252,6 @@ ${indentation} output = ${topTarget}.`;
|
|
|
1252
1252
|
body += indentation + uniqueName + " = " + base.concatTokens() + ".\n";
|
|
1253
1253
|
}
|
|
1254
1254
|
let end = "";
|
|
1255
|
-
/*
|
|
1256
|
-
for (const forLoop of valueBody?.findDirectExpressions(Expressions.For) || []) {
|
|
1257
|
-
const outlineFor = this.outlineFor(forLoop, indentation, lowFile, highSyntax);
|
|
1258
|
-
body += outlineFor.body;
|
|
1259
|
-
end = outlineFor.end + `.\n` + end;
|
|
1260
|
-
indentation += " ";
|
|
1261
|
-
}
|
|
1262
|
-
*/
|
|
1263
1255
|
let structureName = uniqueName;
|
|
1264
1256
|
let added = false;
|
|
1265
1257
|
let skip = false;
|
|
@@ -1284,6 +1276,9 @@ ${indentation} output = ${topTarget}.`;
|
|
|
1284
1276
|
indentation += " ";
|
|
1285
1277
|
}
|
|
1286
1278
|
else if (b.get() instanceof Expressions.Source) {
|
|
1279
|
+
if ((valueBody === null || valueBody === void 0 ? void 0 : valueBody.getChildren().length) === 1) {
|
|
1280
|
+
body += indentation + uniqueName + " = " + b.concatTokens() + `.\n`;
|
|
1281
|
+
}
|
|
1287
1282
|
structureName = b.concatTokens();
|
|
1288
1283
|
if (base && (valueBody === null || valueBody === void 0 ? void 0 : valueBody.findDirectTokenByText("(")) === undefined) {
|
|
1289
1284
|
structureName = uniqueName;
|
package/build/src/rules/index.js
CHANGED
|
@@ -25,6 +25,7 @@ __exportStar(require("./begin_end_names"), exports);
|
|
|
25
25
|
__exportStar(require("./begin_single_include"), exports);
|
|
26
26
|
__exportStar(require("./call_transaction_authority_check"), exports);
|
|
27
27
|
__exportStar(require("./cds_parser_error"), exports);
|
|
28
|
+
__exportStar(require("./cds_legacy_view"), exports);
|
|
28
29
|
__exportStar(require("./chain_mainly_declarations"), exports);
|
|
29
30
|
__exportStar(require("./check_abstract"), exports);
|
|
30
31
|
__exportStar(require("./check_comments"), exports);
|
|
@@ -36,6 +37,7 @@ __exportStar(require("./check_syntax"), exports);
|
|
|
36
37
|
__exportStar(require("./classic_exceptions_overlap"), exports);
|
|
37
38
|
__exportStar(require("./check_text_elements"), exports);
|
|
38
39
|
__exportStar(require("./check_transformation_exists"), exports);
|
|
40
|
+
__exportStar(require("./superfluous_value"), exports);
|
|
39
41
|
__exportStar(require("./class_attribute_names"), exports);
|
|
40
42
|
__exportStar(require("./cloud_types"), exports);
|
|
41
43
|
__exportStar(require("./colon_missing_space"), exports);
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SuperfluousValue = exports.SuperfluousValueConf = void 0;
|
|
4
|
+
const issue_1 = require("../issue");
|
|
5
|
+
const _abap_rule_1 = require("./_abap_rule");
|
|
6
|
+
const _basic_rule_config_1 = require("./_basic_rule_config");
|
|
7
|
+
const Expressions = require("../abap/2_statements/expressions");
|
|
8
|
+
const Statements = require("../abap/2_statements/statements");
|
|
9
|
+
const _irule_1 = require("./_irule");
|
|
10
|
+
const version_1 = require("../version");
|
|
11
|
+
class SuperfluousValueConf extends _basic_rule_config_1.BasicRuleConfig {
|
|
12
|
+
}
|
|
13
|
+
exports.SuperfluousValueConf = SuperfluousValueConf;
|
|
14
|
+
class SuperfluousValue extends _abap_rule_1.ABAPRule {
|
|
15
|
+
constructor() {
|
|
16
|
+
super(...arguments);
|
|
17
|
+
this.conf = new SuperfluousValueConf();
|
|
18
|
+
}
|
|
19
|
+
getMetadata() {
|
|
20
|
+
return {
|
|
21
|
+
key: "superfluous_value",
|
|
22
|
+
title: "Superfluous VALUE",
|
|
23
|
+
shortDescription: `Find superfluous VALUE expressions`,
|
|
24
|
+
extendedInformation: `Left hand side is inline, VALUE is inferred, value body is simple, from v740sp02 and up`,
|
|
25
|
+
tags: [_irule_1.RuleTag.SingleFile],
|
|
26
|
+
badExample: `DATA(message_entry) = VALUE #( message_table[ msgno = msgno ] ).`,
|
|
27
|
+
goodExample: `DATA(message_entry) = message_table[ msgno = msgno ].`,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
getConfig() {
|
|
31
|
+
return this.conf;
|
|
32
|
+
}
|
|
33
|
+
setConfig(conf) {
|
|
34
|
+
this.conf = conf;
|
|
35
|
+
}
|
|
36
|
+
runParsed(file) {
|
|
37
|
+
var _a, _b;
|
|
38
|
+
const output = [];
|
|
39
|
+
if (this.reg.getConfig().getVersion() < version_1.Version.v740sp02
|
|
40
|
+
&& this.reg.getConfig().getVersion() !== version_1.Version.Cloud) {
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
const struc = file.getStructure();
|
|
44
|
+
if (struc === undefined) {
|
|
45
|
+
return []; // syntax error
|
|
46
|
+
}
|
|
47
|
+
for (const m of struc.findAllStatements(Statements.Move)) {
|
|
48
|
+
if (((_a = m.findDirectExpression(Expressions.Target)) === null || _a === void 0 ? void 0 : _a.findDirectExpression(Expressions.InlineData)) === undefined) {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
const source = m.findDirectExpression(Expressions.Source);
|
|
52
|
+
if (source === undefined) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
const type = (_b = source.findDirectExpression(Expressions.TypeNameOrInfer)) === null || _b === void 0 ? void 0 : _b.concatTokens();
|
|
56
|
+
if (type !== "#") {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
const body = source.findDirectExpression(Expressions.ValueBody);
|
|
60
|
+
if (body === undefined) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (body.getChildren().length === 1) {
|
|
64
|
+
const message = "Superfluous VALUE expression";
|
|
65
|
+
const issue = issue_1.Issue.atStatement(file, m, message, this.getMetadata().key, this.conf.severity);
|
|
66
|
+
output.push(issue);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return output;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
exports.SuperfluousValue = SuperfluousValue;
|
|
73
|
+
//# sourceMappingURL=superfluous_value.js.map
|
|
@@ -25,20 +25,28 @@ class UnnecessaryPragma extends _abap_rule_1.ABAPRule {
|
|
|
25
25
|
|
|
26
26
|
* NEEDED without definition
|
|
27
27
|
|
|
28
|
-
* NO_TEXT without texts
|
|
28
|
+
* NO_TEXT without texts
|
|
29
|
+
|
|
30
|
+
* SUBRC_OK where sy-subrc is checked`,
|
|
29
31
|
tags: [_irule_1.RuleTag.SingleFile],
|
|
30
32
|
badExample: `TRY.
|
|
31
33
|
...
|
|
32
34
|
CATCH zcx_abapgit_exception ##NO_HANDLER.
|
|
33
35
|
RETURN. " it has a handler
|
|
34
36
|
ENDTRY.
|
|
35
|
-
MESSAGE w125(zbar) WITH c_foo INTO message ##NEEDED ##NO_TEXT
|
|
37
|
+
MESSAGE w125(zbar) WITH c_foo INTO message ##NEEDED ##NO_TEXT.
|
|
38
|
+
SELECT SINGLE * FROM tadir INTO @DATA(sdfs) ##SUBRC_OK.
|
|
39
|
+
IF sy-subrc <> 0.
|
|
40
|
+
ENDIF.`,
|
|
36
41
|
goodExample: `TRY.
|
|
37
42
|
...
|
|
38
43
|
CATCH zcx_abapgit_exception.
|
|
39
44
|
RETURN.
|
|
40
45
|
ENDTRY.
|
|
41
|
-
MESSAGE w125(zbar) WITH c_foo INTO message
|
|
46
|
+
MESSAGE w125(zbar) WITH c_foo INTO message.
|
|
47
|
+
SELECT SINGLE * FROM tadir INTO @DATA(sdfs).
|
|
48
|
+
IF sy-subrc <> 0.
|
|
49
|
+
ENDIF.`,
|
|
42
50
|
};
|
|
43
51
|
}
|
|
44
52
|
getConfig() {
|
|
@@ -53,6 +61,7 @@ MESSAGE w125(zbar) WITH c_foo INTO message.`,
|
|
|
53
61
|
const statements = file.getStatements();
|
|
54
62
|
for (let i = 0; i < statements.length; i++) {
|
|
55
63
|
const statement = statements[i];
|
|
64
|
+
const nextStatement = statements[i + 1];
|
|
56
65
|
if (statement.get() instanceof Statements.EndTry) {
|
|
57
66
|
noHandler = false;
|
|
58
67
|
}
|
|
@@ -70,6 +79,7 @@ MESSAGE w125(zbar) WITH c_foo INTO message.`,
|
|
|
70
79
|
}
|
|
71
80
|
issues.push(...this.checkText(statement, file));
|
|
72
81
|
issues.push(...this.checkNeeded(statement, file));
|
|
82
|
+
issues.push(...this.checkSubrc(statement, nextStatement, file));
|
|
73
83
|
}
|
|
74
84
|
return issues;
|
|
75
85
|
}
|
|
@@ -85,6 +95,18 @@ MESSAGE w125(zbar) WITH c_foo INTO message.`,
|
|
|
85
95
|
}
|
|
86
96
|
return [];
|
|
87
97
|
}
|
|
98
|
+
checkSubrc(statement, next, file) {
|
|
99
|
+
const p = statement.getPragmas().find(t => t.getStr().toUpperCase() === "##SUBRC_OK");
|
|
100
|
+
if (p === undefined) {
|
|
101
|
+
return [];
|
|
102
|
+
}
|
|
103
|
+
const concat = next.concatTokens().toUpperCase();
|
|
104
|
+
if (concat.includes(" SY-SUBRC")) {
|
|
105
|
+
const message = "SUBRC_OK can be removed as sy-subrc is checked";
|
|
106
|
+
return [issue_1.Issue.atToken(file, p, message, this.getMetadata().key, this.getConfig().severity)];
|
|
107
|
+
}
|
|
108
|
+
return [];
|
|
109
|
+
}
|
|
88
110
|
checkNeeded(statement, file) {
|
|
89
111
|
const p = statement.getPragmas().find(t => t.getStr().toUpperCase() === "##NEEDED");
|
|
90
112
|
if (p === undefined) {
|