@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.
Files changed (45) hide show
  1. package/build/abaplint.d.ts +10 -0
  2. package/build/src/abap/1_lexer/lexer.js +1 -1
  3. package/build/src/abap/1_lexer/lexer_stream.js +8 -0
  4. package/build/src/abap/3_structures/structures/_combi.js +61 -112
  5. package/build/src/abap/5_syntax/basic_types.js +4 -4
  6. package/build/src/abap/5_syntax/expressions/_check_database_work_area.js +127 -0
  7. package/build/src/abap/5_syntax/expressions/attribute_name.js +1 -1
  8. package/build/src/abap/5_syntax/expressions/conv_body.js +2 -2
  9. package/build/src/abap/5_syntax/expressions/field_chain.js +1 -1
  10. package/build/src/abap/5_syntax/expressions/form_param.js +1 -1
  11. package/build/src/abap/5_syntax/expressions/method_parameters.js +2 -2
  12. package/build/src/abap/5_syntax/expressions/select.js +1 -2
  13. package/build/src/abap/5_syntax/expressions/source.js +19 -3
  14. package/build/src/abap/5_syntax/statements/assign.js +15 -1
  15. package/build/src/abap/5_syntax/statements/insert_database.js +6 -3
  16. package/build/src/abap/5_syntax/statements/loop.js +1 -1
  17. package/build/src/abap/5_syntax/statements/modify_database.js +8 -4
  18. package/build/src/abap/5_syntax/statements/update_database.js +7 -3
  19. package/build/src/abap/5_syntax/statements/when_type.js +1 -1
  20. package/build/src/abap/types/class_attributes.js +1 -1
  21. package/build/src/cds/cds_lexer.js +1 -1
  22. package/build/src/lsp/help.js +2 -2
  23. package/build/src/objects/data_element.js +1 -1
  24. package/build/src/objects/table.js +1 -0
  25. package/build/src/registry.js +1 -1
  26. package/build/src/rules/align_pseudo_comments.js +1 -1
  27. package/build/src/rules/align_type_expressions.js +1 -1
  28. package/build/src/rules/change_if_to_case.js +1 -1
  29. package/build/src/rules/check_ddic.js +1 -1
  30. package/build/src/rules/class_attribute_names.js +1 -3
  31. package/build/src/rules/downport.js +122 -24
  32. package/build/src/rules/empty_structure.js +26 -0
  33. package/build/src/rules/functional_writing.js +1 -1
  34. package/build/src/rules/generic_regex.js +86 -0
  35. package/build/src/rules/index.js +1 -0
  36. package/build/src/rules/keyword_case.js +1 -1
  37. package/build/src/rules/local_class_naming.js +1 -1
  38. package/build/src/rules/many_parentheses.js +1 -1
  39. package/build/src/rules/obsolete_statement.js +3 -7
  40. package/build/src/rules/parser_missing_space.js +1 -2
  41. package/build/src/rules/prefer_raise_exception_new.js +2 -8
  42. package/build/src/rules/xml_consistency.js +16 -0
  43. package/build/src/utils/form_length_stats.js +1 -1
  44. package/build/src/utils/method_length_stats.js +1 -1
  45. 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
@@ -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
  }
@@ -58,7 +58,7 @@ ENDCLASS.`,
58
58
  continue;
59
59
  }
60
60
  const className = classDef.name;
61
- let expected = "";
61
+ let expected;
62
62
  if (classDef.isForTesting) {
63
63
  expected = this.conf.test;
64
64
  }
@@ -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
- let token = undefined;
490
- if (statement instanceof Statements.ClassDefinitionLoad) {
491
- token = statementNode.getChildren()[3].getFirstToken();
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 = new position_1.Position(0, 0);
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
- let contentFix = undefined;
97
- if (withExporting) {
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
@@ -76,7 +76,7 @@ class FormLengthStats {
76
76
  return res;
77
77
  }
78
78
  static findName(stat) {
79
- let name = "";
79
+ let name;
80
80
  const nameExpr = stat.findFirstExpression(expressions_1.FormName);
81
81
  if (nameExpr) {
82
82
  name = nameExpr.getFirstToken().getStr();
@@ -82,7 +82,7 @@ class MethodLengthStats {
82
82
  return res;
83
83
  }
84
84
  static findName(stat) {
85
- let name = "";
85
+ let name;
86
86
  const nameExpr = stat.findFirstExpression(expressions_1.MethodName);
87
87
  if (nameExpr) {
88
88
  name = nameExpr.getFirstToken().getStr();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/core",
3
- "version": "2.120.71",
3
+ "version": "2.120.73",
4
4
  "description": "abaplint - Core API",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/abaplint.d.ts",