@abaplint/core 2.120.71 → 2.120.73
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 +10 -0
- package/build/src/abap/1_lexer/lexer.js +1 -1
- package/build/src/abap/1_lexer/lexer_stream.js +8 -0
- package/build/src/abap/3_structures/structures/_combi.js +61 -112
- package/build/src/abap/5_syntax/basic_types.js +4 -4
- package/build/src/abap/5_syntax/expressions/_check_database_work_area.js +127 -0
- package/build/src/abap/5_syntax/expressions/attribute_name.js +1 -1
- package/build/src/abap/5_syntax/expressions/conv_body.js +2 -2
- package/build/src/abap/5_syntax/expressions/field_chain.js +1 -1
- package/build/src/abap/5_syntax/expressions/form_param.js +1 -1
- package/build/src/abap/5_syntax/expressions/method_parameters.js +2 -2
- package/build/src/abap/5_syntax/expressions/select.js +1 -2
- package/build/src/abap/5_syntax/expressions/source.js +19 -3
- package/build/src/abap/5_syntax/statements/assign.js +15 -1
- package/build/src/abap/5_syntax/statements/insert_database.js +6 -3
- package/build/src/abap/5_syntax/statements/loop.js +1 -1
- package/build/src/abap/5_syntax/statements/modify_database.js +8 -4
- package/build/src/abap/5_syntax/statements/update_database.js +7 -3
- package/build/src/abap/5_syntax/statements/when_type.js +1 -1
- package/build/src/abap/types/class_attributes.js +1 -1
- package/build/src/cds/cds_lexer.js +1 -1
- package/build/src/lsp/help.js +2 -2
- package/build/src/objects/data_element.js +1 -1
- package/build/src/objects/table.js +1 -0
- package/build/src/registry.js +1 -1
- package/build/src/rules/align_pseudo_comments.js +1 -1
- package/build/src/rules/align_type_expressions.js +1 -1
- package/build/src/rules/change_if_to_case.js +1 -1
- package/build/src/rules/check_ddic.js +1 -1
- package/build/src/rules/class_attribute_names.js +1 -3
- package/build/src/rules/downport.js +122 -24
- package/build/src/rules/empty_structure.js +26 -0
- package/build/src/rules/functional_writing.js +1 -1
- package/build/src/rules/generic_regex.js +86 -0
- package/build/src/rules/index.js +1 -0
- package/build/src/rules/keyword_case.js +1 -1
- package/build/src/rules/local_class_naming.js +1 -1
- package/build/src/rules/many_parentheses.js +1 -1
- package/build/src/rules/obsolete_statement.js +3 -7
- package/build/src/rules/parser_missing_space.js +1 -2
- package/build/src/rules/prefer_raise_exception_new.js +2 -8
- package/build/src/rules/xml_consistency.js +16 -0
- package/build/src/utils/form_length_stats.js +1 -1
- package/build/src/utils/method_length_stats.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GenericRegex = exports.GenericRegexConf = void 0;
|
|
4
|
+
const issue_1 = require("../issue");
|
|
5
|
+
const _basic_rule_config_1 = require("./_basic_rule_config");
|
|
6
|
+
const _irule_1 = require("./_irule");
|
|
7
|
+
class GenericRegexConf extends _basic_rule_config_1.BasicRuleConfig {
|
|
8
|
+
constructor() {
|
|
9
|
+
super(...arguments);
|
|
10
|
+
/** List of forbidden regular expressions, case insensitive, checked against each line of every file.
|
|
11
|
+
* Patterns use JavaScript regex syntax without enclosing slashes or flags.
|
|
12
|
+
* @uniqueItems true
|
|
13
|
+
*/
|
|
14
|
+
this.regexes = [];
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.GenericRegexConf = GenericRegexConf;
|
|
18
|
+
class GenericRegex {
|
|
19
|
+
constructor() {
|
|
20
|
+
this.conf = new GenericRegexConf();
|
|
21
|
+
this.regexes = [];
|
|
22
|
+
}
|
|
23
|
+
getMetadata() {
|
|
24
|
+
return {
|
|
25
|
+
key: "generic_regex",
|
|
26
|
+
title: "Generic regex",
|
|
27
|
+
shortDescription: "Report an issue for each match of a configured regular expression.",
|
|
28
|
+
extendedInformation: `Checks each line of every object file, including comments, strings, and XML.
|
|
29
|
+
Patterns use JavaScript regular expression syntax without enclosing slashes or flags.
|
|
30
|
+
Matching is case insensitive and does not span multiple lines. Each non-overlapping match is reported.
|
|
31
|
+
Use the standard exclude configuration to skip files.
|
|
32
|
+
|
|
33
|
+
Example configuration: \`{"generic_regex": {"regexes": ["TODO", "BREAK-POINT"]}}\``,
|
|
34
|
+
tags: [_irule_1.RuleTag.SingleFile],
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
getConfig() {
|
|
38
|
+
return this.conf;
|
|
39
|
+
}
|
|
40
|
+
setConfig(conf) {
|
|
41
|
+
var _a;
|
|
42
|
+
this.conf = Object.assign(new GenericRegexConf(), conf);
|
|
43
|
+
this.conf.regexes = (_a = this.conf.regexes) !== null && _a !== void 0 ? _a : [];
|
|
44
|
+
}
|
|
45
|
+
initialize(_reg) {
|
|
46
|
+
this.regexes = this.conf.regexes.map(pattern => {
|
|
47
|
+
try {
|
|
48
|
+
return new RegExp(pattern, "gi");
|
|
49
|
+
}
|
|
50
|
+
catch (_a) {
|
|
51
|
+
throw new Error(`generic_regex: Invalid regular expression "${pattern}"`);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
return this;
|
|
55
|
+
}
|
|
56
|
+
run(obj) {
|
|
57
|
+
const issues = [];
|
|
58
|
+
if (this.regexes.length === 0) {
|
|
59
|
+
return issues;
|
|
60
|
+
}
|
|
61
|
+
for (const file of obj.getFiles()) {
|
|
62
|
+
const rows = file.getRawRows();
|
|
63
|
+
for (let row = 0; row < rows.length; row++) {
|
|
64
|
+
const text = rows[row].replace(/\r$/, "");
|
|
65
|
+
for (const regex of this.regexes) {
|
|
66
|
+
regex.lastIndex = 0;
|
|
67
|
+
for (;;) {
|
|
68
|
+
const match = regex.exec(text);
|
|
69
|
+
if (match === null) {
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
const startCol = match.index + 1;
|
|
73
|
+
const message = `Text matches forbidden regular expression "${regex.source}"`;
|
|
74
|
+
issues.push(issue_1.Issue.atRowRange(file, row + 1, startCol, startCol + match[0].length, message, this.getMetadata().key, this.conf.severity));
|
|
75
|
+
if (match[0].length === 0) {
|
|
76
|
+
regex.lastIndex++;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return issues;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
exports.GenericRegex = GenericRegex;
|
|
86
|
+
//# sourceMappingURL=generic_regex.js.map
|
package/build/src/rules/index.js
CHANGED
|
@@ -82,6 +82,7 @@ __exportStar(require("./fully_type_constants"), exports);
|
|
|
82
82
|
__exportStar(require("./fully_type_itabs"), exports);
|
|
83
83
|
__exportStar(require("./function_module_recommendations"), exports);
|
|
84
84
|
__exportStar(require("./functional_writing"), exports);
|
|
85
|
+
__exportStar(require("./generic_regex"), exports);
|
|
85
86
|
__exportStar(require("./global_class"), exports);
|
|
86
87
|
__exportStar(require("./identical_conditions"), exports);
|
|
87
88
|
__exportStar(require("./identical_contents"), exports);
|
|
@@ -215,7 +215,7 @@ class KeywordCase extends _abap_rule_1.ABAPRule {
|
|
|
215
215
|
const firstToken = tokens[0].token;
|
|
216
216
|
const lastToken = tokens[tokens.length - 1].token;
|
|
217
217
|
const firstTokenValue = firstToken.getStr();
|
|
218
|
-
let description
|
|
218
|
+
let description;
|
|
219
219
|
if (first.keyword === true) {
|
|
220
220
|
description = `Keyword should be ${this.conf.style} case: "${firstTokenValue}"`;
|
|
221
221
|
}
|
|
@@ -86,7 +86,7 @@ ENDIF.
|
|
|
86
86
|
issues.push(...this.analyzeCondition(file, cond));
|
|
87
87
|
}
|
|
88
88
|
for (const sub of structure.findAllExpressionsMulti([Expressions.CondSub, Expressions.ComponentCondSub])) {
|
|
89
|
-
let cond
|
|
89
|
+
let cond;
|
|
90
90
|
if (sub.get() instanceof Expressions.CondSub) {
|
|
91
91
|
cond = sub.findDirectExpressions(Expressions.Cond);
|
|
92
92
|
}
|
|
@@ -486,13 +486,9 @@ ENDIF.`,
|
|
|
486
486
|
}
|
|
487
487
|
else if (statement instanceof Statements.ClassDefinitionLoad ||
|
|
488
488
|
statement instanceof Statements.InterfaceLoad) {
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
}
|
|
493
|
-
else {
|
|
494
|
-
token = statementNode.getChildren()[2].getFirstToken();
|
|
495
|
-
}
|
|
489
|
+
const token = statement instanceof Statements.ClassDefinitionLoad
|
|
490
|
+
? statementNode.getChildren()[3].getFirstToken()
|
|
491
|
+
: statementNode.getChildren()[2].getFirstToken();
|
|
496
492
|
let startPosition = token.getStart();
|
|
497
493
|
startPosition = new position_1.Position(startPosition.getRow(), startPosition.getCol() - 1);
|
|
498
494
|
return edit_helper_1.EditHelper.deleteRange(file, startPosition, token.getEnd());
|
|
@@ -36,7 +36,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.ParserMissingSpace = exports.ParserMissingSpaceConf = void 0;
|
|
37
37
|
const Expressions = __importStar(require("../abap/2_statements/expressions"));
|
|
38
38
|
const issue_1 = require("../issue");
|
|
39
|
-
const position_1 = require("../position");
|
|
40
39
|
const _abap_rule_1 = require("./_abap_rule");
|
|
41
40
|
const nodes_1 = require("../abap/nodes");
|
|
42
41
|
const _basic_rule_config_1 = require("./_basic_rule_config");
|
|
@@ -69,7 +68,7 @@ This rule makes sure the spaces are consistently required across the language.`,
|
|
|
69
68
|
}
|
|
70
69
|
runParsed(file) {
|
|
71
70
|
const issues = [];
|
|
72
|
-
let start
|
|
71
|
+
let start;
|
|
73
72
|
for (const statement of file.getStatements()) {
|
|
74
73
|
const missing = this.missingSpace(statement);
|
|
75
74
|
if (missing) {
|
|
@@ -93,14 +93,8 @@ From 752 and up`,
|
|
|
93
93
|
}
|
|
94
94
|
getFix(file, statement, withExporting) {
|
|
95
95
|
const children = statement.getChildren();
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
const fixText = "( " + children[5].concatTokens() + " ).";
|
|
99
|
-
contentFix = edit_helper_1.EditHelper.replaceRange(file, children[3].getLastToken().getEnd(), statement.getEnd(), fixText);
|
|
100
|
-
}
|
|
101
|
-
else {
|
|
102
|
-
contentFix = edit_helper_1.EditHelper.replaceRange(file, children[3].getLastToken().getEnd(), statement.getEnd(), "( ).");
|
|
103
|
-
}
|
|
96
|
+
const fixText = withExporting ? "( " + children[5].concatTokens() + " )." : "( ).";
|
|
97
|
+
const contentFix = edit_helper_1.EditHelper.replaceRange(file, children[3].getLastToken().getEnd(), statement.getEnd(), fixText);
|
|
104
98
|
const replaceType = edit_helper_1.EditHelper.replaceToken(file, children[2].getFirstToken(), "NEW");
|
|
105
99
|
return edit_helper_1.EditHelper.merge(contentFix, replaceType);
|
|
106
100
|
}
|
|
@@ -67,6 +67,7 @@ class XMLConsistency {
|
|
|
67
67
|
* Naming for CLAS and INTF objects
|
|
68
68
|
* QUAN fields in TABL objects have reference table and field values
|
|
69
69
|
* Transparent TABL objects have delivery class and size category set
|
|
70
|
+
* TABL fields with a built-in type carry the INTTYPE abapGit serializes for it, for the confirmed pairs
|
|
70
71
|
* Lock parameter names in ENQU objects are max 16 characters
|
|
71
72
|
* Texts and translations do not exceed maximum allowed length.`,
|
|
72
73
|
tags: [_irule_1.RuleTag.Naming, _irule_1.RuleTag.Syntax],
|
|
@@ -333,6 +334,12 @@ class XMLConsistency {
|
|
|
333
334
|
const message = `QUAN field ${field.FIELDNAME} must have REFTABLE and REFFIELD set`;
|
|
334
335
|
issues.push(issue_1.Issue.atRow(file, 1, message, this.getMetadata().key, this.conf.severity));
|
|
335
336
|
}
|
|
337
|
+
const expected = field.DATATYPE ? XMLConsistency.intTypes[field.DATATYPE] : undefined;
|
|
338
|
+
if (expected !== undefined && field.INTTYPE !== undefined && field.INTTYPE !== expected) {
|
|
339
|
+
const message = `Field ${field.FIELDNAME}: INTTYPE "${field.INTTYPE}" does not match DATATYPE ${field.DATATYPE}, ` +
|
|
340
|
+
`abapGit serializes "${expected}"`;
|
|
341
|
+
issues.push(issue_1.Issue.atRow(file, 1, message, this.getMetadata().key, this.conf.severity));
|
|
342
|
+
}
|
|
336
343
|
}
|
|
337
344
|
if (obj.getTableCategory() === Objects.TableCategory.Transparent) {
|
|
338
345
|
// Confirmed reserved database field names, see issue #4331, DAY and HOUR reported by activation.
|
|
@@ -356,4 +363,13 @@ class XMLConsistency {
|
|
|
356
363
|
}
|
|
357
364
|
}
|
|
358
365
|
exports.XMLConsistency = XMLConsistency;
|
|
366
|
+
// INTTYPE that abapGit serializes for a built-in DATATYPE, confirmed by exported tables;
|
|
367
|
+
// a different value activates, but shows as a diff on every pull
|
|
368
|
+
XMLConsistency.intTypes = {
|
|
369
|
+
"CHAR": "C", "CLNT": "C", "CUKY": "C", "LANG": "C",
|
|
370
|
+
"DATS": "D", "TIMS": "T",
|
|
371
|
+
"INT4": "X", "RAW": "X",
|
|
372
|
+
"DEC": "P", "CURR": "P",
|
|
373
|
+
"STRG": "g", "SSTR": "g", "RSTR": "y",
|
|
374
|
+
};
|
|
359
375
|
//# sourceMappingURL=xml_consistency.js.map
|