@abaplint/core 2.120.73 → 2.120.75

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 +6 -1
  2. package/build/src/abap/2_statements/combi.js +143 -51
  3. package/build/src/abap/2_statements/expressions/method_param_optional.js +3 -1
  4. package/build/src/abap/5_syntax/basic_types.js +67 -23
  5. package/build/src/abap/5_syntax/statements/append.js +6 -0
  6. package/build/src/abap/types/method_definition.js +22 -0
  7. package/build/src/abap/types/method_parameters.js +57 -0
  8. package/build/src/ddic.js +1 -1
  9. package/build/src/objects/data_definition.js +9 -1
  10. package/build/src/objects/domain.js +4 -1
  11. package/build/src/registry.js +1 -1
  12. package/build/src/rules/abapdoc_html_tag.js +123 -0
  13. package/build/src/rules/abapdoc_leading_at.js +117 -0
  14. package/build/src/rules/abapdoc_parameter_names.js +149 -0
  15. package/build/src/rules/cds_check_syntax.js +4 -4
  16. package/build/src/rules/change_if_to_case.js +3 -2
  17. package/build/src/rules/changing_sorted_line.js +235 -0
  18. package/build/src/rules/class_attribute_names.js +15 -6
  19. package/build/src/rules/delete_index_in_loop.js +163 -0
  20. package/build/src/rules/final_newline.js +78 -0
  21. package/build/src/rules/forbidden_identifier.js +4 -3
  22. package/build/src/rules/forbidden_void_type.js +4 -9
  23. package/build/src/rules/index.js +11 -0
  24. package/build/src/rules/inline_packed_computation.js +220 -0
  25. package/build/src/rules/intf_referencing_clas.js +3 -1
  26. package/build/src/rules/line_only_punc.js +1 -1
  27. package/build/src/rules/local_class_naming.js +15 -2
  28. package/build/src/rules/local_variable_names.js +18 -9
  29. package/build/src/rules/macro_naming.js +3 -2
  30. package/build/src/rules/method_parameter_names.js +17 -7
  31. package/build/src/rules/modify_only_own_db_tables.js +3 -2
  32. package/build/src/rules/no_exclamation_escape.js +32 -2
  33. package/build/src/rules/no_prefixes.js +25 -12
  34. package/build/src/rules/object_naming.js +18 -3
  35. package/build/src/rules/prefer_inline_cast.js +276 -0
  36. package/build/src/rules/range_row_values.js +200 -0
  37. package/build/src/rules/selection_screen_naming.js +21 -2
  38. package/build/src/rules/sicf_consistency.js +1 -2
  39. package/build/src/rules/sort_empty_key.js +188 -0
  40. package/build/src/rules/subrc_after_assign.js +220 -0
  41. package/build/src/rules/types_naming.js +3 -2
  42. package/build/src/rules/wrong_abapdoc_position.js +58 -11
  43. package/build/src/rules/xml_consistency.js +6 -2
  44. package/build/src/utils/name_validator.js +7 -3
  45. package/package.json +1 -1
@@ -0,0 +1,235 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.ChangingSortedLine = exports.ChangingSortedLineConf = void 0;
37
+ const Expressions = __importStar(require("../abap/2_statements/expressions"));
38
+ const Statements = __importStar(require("../abap/2_statements/statements"));
39
+ const Structures = __importStar(require("../abap/3_structures/structures"));
40
+ const _basic_rule_config_1 = require("./_basic_rule_config");
41
+ const issue_1 = require("../issue");
42
+ const _irule_1 = require("./_irule");
43
+ const syntax_1 = require("../abap/5_syntax/syntax");
44
+ const _abap_object_1 = require("../objects/_abap_object");
45
+ const basic_1 = require("../abap/types/basic");
46
+ const nodes_1 = require("../abap/nodes");
47
+ const _typed_identifier_1 = require("../abap/types/_typed_identifier");
48
+ const tokens_1 = require("../abap/1_lexer/tokens");
49
+ class ChangingSortedLineConf extends _basic_rule_config_1.BasicRuleConfig {
50
+ }
51
+ exports.ChangingSortedLineConf = ChangingSortedLineConf;
52
+ class ChangingSortedLine {
53
+ constructor() {
54
+ this.conf = new ChangingSortedLineConf();
55
+ }
56
+ getMetadata() {
57
+ return {
58
+ key: "changing_sorted_line",
59
+ title: "Line of a sorted or hashed table passed to CHANGING",
60
+ shortDescription: `A field symbol on a whole line of a sorted or hashed table, passed to a CHANGING parameter of a method`,
61
+ extendedInformation: `The key fields of a sorted or hashed table line are write-protected, so the line as a whole is
62
+ write-protected. Binding it to a CHANGING parameter activates, but the call fails at runtime with
63
+ CX_SY_DYN_CALL_ILLEGAL_TYPE, "the actual parameter for ... is write-protected", even when the method does not
64
+ change the key.
65
+
66
+ Only field symbols assigned in the same method, form or function module are checked, via READ TABLE ... ASSIGNING,
67
+ LOOP AT ... ASSIGNING, INSERT ... INTO TABLE ... ASSIGNING and ASSIGN itab[ ... ] TO.
68
+
69
+ Fix: read the line into a work area, pass the work area and MODIFY TABLE ... FROM it afterwards,
70
+ or pass only the non-key fields the method needs.`,
71
+ tags: [_irule_1.RuleTag.SingleFile],
72
+ badExample: `READ TABLE lt_sum WITH TABLE KEY app = lv_app ASSIGNING FIELD-SYMBOL(<sum>).
73
+ add( CHANGING cs_sum = <sum> ).`,
74
+ goodExample: `READ TABLE lt_sum WITH TABLE KEY app = lv_app INTO DATA(ls_sum).
75
+ add( CHANGING cs_sum = ls_sum ).
76
+ MODIFY TABLE lt_sum FROM ls_sum.`,
77
+ };
78
+ }
79
+ getConfig() {
80
+ return this.conf;
81
+ }
82
+ initialize(reg) {
83
+ this.reg = reg;
84
+ return this;
85
+ }
86
+ setConfig(conf) {
87
+ this.conf = conf;
88
+ }
89
+ run(obj) {
90
+ if (!(obj instanceof _abap_object_1.ABAPObject) || obj.getType() === "INTF") {
91
+ return [];
92
+ }
93
+ const issues = [];
94
+ let spaghetti = undefined;
95
+ for (const file of obj.getABAPFiles()) {
96
+ const stru = file.getStructure();
97
+ if (stru === undefined || stru.findFirstExpression(Expressions.MethodParameters) === undefined) {
98
+ continue;
99
+ }
100
+ if (spaghetti === undefined) {
101
+ spaghetti = new syntax_1.SyntaxLogic(this.reg, obj).run().spaghetti;
102
+ }
103
+ const blocks = [...stru.findAllStructures(Structures.Method),
104
+ ...stru.findAllStructures(Structures.Form),
105
+ ...stru.findAllStructures(Structures.FunctionModule)];
106
+ for (const block of blocks) {
107
+ // field symbol name -> name of the sorted or hashed table it points into
108
+ const lines = new Map();
109
+ for (const statement of block.findAllStatementNodes()) {
110
+ for (const p of statement.findAllExpressions(Expressions.MethodParameters)) {
111
+ this.checkChanging(p, lines, spaghetti, file, issues);
112
+ }
113
+ this.updateAssigned(statement, lines, spaghetti, file);
114
+ }
115
+ }
116
+ }
117
+ return issues;
118
+ }
119
+ ////////////////
120
+ checkChanging(params, lines, spaghetti, file, issues) {
121
+ var _a, _b;
122
+ let changing = false;
123
+ for (const child of params.getChildren()) {
124
+ const str = child.concatTokens().toUpperCase();
125
+ if (child instanceof nodes_1.ExpressionNode && changing === true && child.get() instanceof Expressions.ParameterListT) {
126
+ for (const p of child.findDirectExpressions(Expressions.ParameterT)) {
127
+ const target = p.findDirectExpression(Expressions.Target);
128
+ const fs = (target === null || target === void 0 ? void 0 : target.getChildren().length) === 1 ? target.findDirectExpression(Expressions.TargetFieldSymbol) : undefined;
129
+ if (fs === undefined) {
130
+ continue;
131
+ }
132
+ const table = lines.get(fs.concatTokens().toUpperCase());
133
+ const type = (_a = this.findReference(fs.getFirstToken().getStart(), spaghetti, file)) === null || _a === void 0 ? void 0 : _a.getType();
134
+ if (table === undefined || type === undefined || type.isGeneric()) {
135
+ continue;
136
+ }
137
+ const name = (_b = p.findDirectExpression(Expressions.ParameterName)) === null || _b === void 0 ? void 0 : _b.concatTokens();
138
+ const message = `Line of sorted or hashed table ${table} passed to CHANGING ${name} is write-protected, ` +
139
+ `the call fails at runtime. Use a work area and MODIFY TABLE ... FROM, or pass only non-key fields`;
140
+ issues.push(issue_1.Issue.atToken(file, fs.getFirstToken(), message, this.getMetadata().key, this.conf.severity));
141
+ }
142
+ }
143
+ changing = str === "CHANGING";
144
+ }
145
+ }
146
+ /** Tracks which field symbols the last assignment pointed to a whole line of a sorted or hashed table */
147
+ updateAssigned(statement, lines, spaghetti, file) {
148
+ var _a, _b, _c;
149
+ var _d;
150
+ const get = statement.get();
151
+ const fs = get instanceof Statements.Unassign
152
+ ? statement.findDirectExpression(Expressions.TargetFieldSymbol)
153
+ : (_a = statement.findFirstExpression(Expressions.FSTarget)) === null || _a === void 0 ? void 0 : _a.findFirstExpression(Expressions.TargetFieldSymbol);
154
+ if (fs === undefined) {
155
+ return;
156
+ }
157
+ const name = fs.concatTokens().toUpperCase();
158
+ let table = undefined;
159
+ let isTableExpression = false;
160
+ if (get instanceof Statements.ReadTable) {
161
+ table = (_d = statement.findDirectExpression(Expressions.SimpleSource2)) !== null && _d !== void 0 ? _d : statement.findDirectExpression(Expressions.Source);
162
+ }
163
+ else if (get instanceof Statements.Loop) {
164
+ table = (_b = statement.findDirectExpression(Expressions.LoopSource)) === null || _b === void 0 ? void 0 : _b.getFirstChild();
165
+ }
166
+ else if (get instanceof Statements.InsertInternal && statement.findDirectTokenByText("TABLE") !== undefined) {
167
+ table = statement.findDirectExpression(Expressions.Target);
168
+ }
169
+ else if (get instanceof Statements.Assign) {
170
+ table = (_c = statement.findDirectExpression(Expressions.AssignSource)) === null || _c === void 0 ? void 0 : _c.getFirstChild();
171
+ isTableExpression = true;
172
+ }
173
+ const tableType = table instanceof nodes_1.ExpressionNode ? this.findTableType(table, isTableExpression, spaghetti, file) : undefined;
174
+ if (table instanceof nodes_1.ExpressionNode && tableType instanceof basic_1.TableType
175
+ && (tableType.getAccessType() === basic_1.TableAccessType.sorted || tableType.getAccessType() === basic_1.TableAccessType.hashed)) {
176
+ lines.set(name, table.concatTokens().replace(/\[.*$/, "").trim());
177
+ }
178
+ else {
179
+ lines.delete(name);
180
+ }
181
+ }
182
+ /** The type of a table given by a plain field chain of names, components and attributes, else undefined.
183
+ * With tableExpression, the chain must end with a table expression, and the type of the chain before it is returned */
184
+ findTableType(node, tableExpression, spaghetti, file) {
185
+ var _a, _b;
186
+ if (!(node.get() instanceof Expressions.Target)) {
187
+ const chain = node.getChildren().length === 1 ? node.findDirectExpression(Expressions.FieldChain) : undefined;
188
+ if (chain === undefined) {
189
+ return undefined;
190
+ }
191
+ node = chain;
192
+ }
193
+ const children = [...node.getChildren()];
194
+ if (tableExpression === true) {
195
+ if (!(((_a = children.pop()) === null || _a === void 0 ? void 0 : _a.get()) instanceof Expressions.TableExpression)) {
196
+ return undefined;
197
+ }
198
+ }
199
+ let type = undefined;
200
+ for (const child of children) {
201
+ const get = child.get();
202
+ if (get instanceof Expressions.SourceField
203
+ || get instanceof Expressions.SourceFieldSymbol
204
+ || get instanceof Expressions.TargetField
205
+ || get instanceof Expressions.TargetFieldSymbol
206
+ || get instanceof Expressions.AttributeName) {
207
+ type = (_b = this.findReference(child.getFirstToken().getStart(), spaghetti, file)) === null || _b === void 0 ? void 0 : _b.getType();
208
+ }
209
+ else if (get instanceof Expressions.ComponentName) {
210
+ type = type instanceof basic_1.StructureType ? type.getComponentByName(child.concatTokens()) : undefined;
211
+ }
212
+ else if (get instanceof Expressions.ClassName || get instanceof tokens_1.StaticArrow) {
213
+ continue;
214
+ }
215
+ else if (!(get instanceof tokens_1.Dash) && !(get instanceof tokens_1.InstanceArrow)) {
216
+ return undefined;
217
+ }
218
+ if (type === undefined) {
219
+ return undefined;
220
+ }
221
+ }
222
+ return type;
223
+ }
224
+ findReference(start, spaghetti, file) {
225
+ const scope = spaghetti.lookupPosition(start, file.getFilename());
226
+ for (const r of (scope === null || scope === void 0 ? void 0 : scope.getData().references) || []) {
227
+ if (r.position.getStart().equals(start) && r.resolved instanceof _typed_identifier_1.TypedIdentifier) {
228
+ return r.resolved;
229
+ }
230
+ }
231
+ return undefined;
232
+ }
233
+ }
234
+ exports.ChangingSortedLine = ChangingSortedLine;
235
+ //# sourceMappingURL=changing_sorted_line.js.map
@@ -30,6 +30,7 @@ class ClassAttributeNames extends _abap_rule_1.ABAPRule {
30
30
  constructor() {
31
31
  super(...arguments);
32
32
  this.conf = new ClassAttributeNamesConf();
33
+ this.regex = this.compile();
33
34
  }
34
35
  getMetadata() {
35
36
  return {
@@ -57,6 +58,15 @@ ENDCLASS.`,
57
58
  }
58
59
  setConfig(conf) {
59
60
  this.conf = conf;
61
+ this.regex = this.compile();
62
+ }
63
+ compile() {
64
+ return {
65
+ statics: new RegExp(this.conf.statics, "i"),
66
+ instance: new RegExp(this.conf.instance, "i"),
67
+ constants: new RegExp(this.conf.constants, "i"),
68
+ ignorePatterns: name_validator_1.NameValidator.compileIgnorePatterns(this.conf),
69
+ };
60
70
  }
61
71
  runParsed(file, obj) {
62
72
  if (this.conf.patternKind === undefined) {
@@ -89,13 +99,13 @@ ENDCLASS.`,
89
99
  for (const a of attr) {
90
100
  switch (a.level) {
91
101
  case _abap_file_information_1.AttributeLevel.Instance:
92
- ret = ret.concat(this.checkName(a.identifier, this.conf.instance));
102
+ ret = ret.concat(this.checkName(a.identifier, this.conf.instance, this.regex.instance));
93
103
  break;
94
104
  case _abap_file_information_1.AttributeLevel.Static:
95
- ret = ret.concat(this.checkName(a.identifier, this.conf.statics));
105
+ ret = ret.concat(this.checkName(a.identifier, this.conf.statics, this.regex.statics));
96
106
  break;
97
107
  case _abap_file_information_1.AttributeLevel.Constant:
98
- ret = ret.concat(this.checkName(a.identifier, this.conf.constants));
108
+ ret = ret.concat(this.checkName(a.identifier, this.conf.constants, this.regex.constants));
99
109
  break;
100
110
  default:
101
111
  break;
@@ -103,11 +113,10 @@ ENDCLASS.`,
103
113
  }
104
114
  return ret;
105
115
  }
106
- checkName(attr, expected) {
116
+ checkName(attr, expected, regex) {
107
117
  const ret = [];
108
- const regex = new RegExp(expected, "i");
109
118
  const name = attr.getName();
110
- if (name_validator_1.NameValidator.violatesRule(name, regex, this.conf)) {
119
+ if (name_validator_1.NameValidator.violatesRule(name, regex, this.conf, this.regex.ignorePatterns)) {
111
120
  const issue = issue_1.Issue.atIdentifier(attr, this.getDescription(name, expected), this.getMetadata().key, this.conf.severity);
112
121
  ret.push(issue);
113
122
  }
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.DeleteIndexInLoop = exports.DeleteIndexInLoopConf = void 0;
37
+ const Statements = __importStar(require("../abap/2_statements/statements"));
38
+ const Expressions = __importStar(require("../abap/2_statements/expressions"));
39
+ const issue_1 = require("../issue");
40
+ const _basic_rule_config_1 = require("./_basic_rule_config");
41
+ const _abap_rule_1 = require("./_abap_rule");
42
+ const _irule_1 = require("./_irule");
43
+ const token_node_1 = require("../abap/nodes/token_node");
44
+ const _statement_1 = require("../abap/2_statements/statements/_statement");
45
+ class DeleteIndexInLoopConf extends _basic_rule_config_1.BasicRuleConfig {
46
+ }
47
+ exports.DeleteIndexInLoopConf = DeleteIndexInLoopConf;
48
+ class DeleteIndexInLoop extends _abap_rule_1.ABAPRule {
49
+ constructor() {
50
+ super(...arguments);
51
+ this.conf = new DeleteIndexInLoopConf();
52
+ }
53
+ getMetadata() {
54
+ return {
55
+ key: "delete_index_in_loop",
56
+ title: "DELETE INDEX sy-tabix inside a LOOP over the same table",
57
+ shortDescription: `Reports DELETE itab INDEX sy-tabix inside a LOOP AT the same table`,
58
+ extendedInformation: `sy-tabix is the index of the loop's current row only until another statement writes it.
59
+ READ TABLE, APPEND, INSERT, COLLECT, a nested LOOP and any method called in the loop body
60
+ all set sy-tabix. After that the DELETE removes a different row, and if sy-tabix is 0 it
61
+ raises the runtime error TABLE_INVALID_INDEX.
62
+
63
+ Use DELETE itab WHERE ..., or collect the rows to keep in a second table.
64
+
65
+ Not reported: DELETE itab INDEX sy-tabix directly after READ TABLE itab, where sy-tabix
66
+ is the index the READ just set.`,
67
+ tags: [_irule_1.RuleTag.SingleFile],
68
+ badExample: `LOOP AT tab INTO row.
69
+ IF row-flag = abap_true.
70
+ DELETE tab INDEX sy-tabix.
71
+ ENDIF.
72
+ ENDLOOP.`,
73
+ goodExample: `DELETE tab WHERE flag = abap_true.`,
74
+ };
75
+ }
76
+ getConfig() {
77
+ return this.conf;
78
+ }
79
+ setConfig(conf) {
80
+ this.conf = conf;
81
+ }
82
+ runParsed(file) {
83
+ const issues = [];
84
+ const statements = file.getStatements();
85
+ for (let i = 0; i < statements.length; i++) {
86
+ const statement = statements[i];
87
+ if (!(statement.get() instanceof Statements.DeleteInternal) || this.byTabix(statement) === false) {
88
+ continue;
89
+ }
90
+ // DELETE TABLE and DELETE ADJACENT DUPLICATES have a keyword before the target
91
+ const target = statement.findDirectExpression(Expressions.Target);
92
+ if (target === undefined || statement.getChildren()[1] !== target) {
93
+ continue;
94
+ }
95
+ const table = target.concatTokens().toUpperCase();
96
+ if (this.previousReadsTable(i, statements, table) === true
97
+ || this.enclosingLoopTables(i, statements).includes(table) === false) {
98
+ continue;
99
+ }
100
+ const message = `DELETE ${target.concatTokens()} INDEX sy-tabix inside LOOP AT the same table,`
101
+ + ` sy-tabix might not be the loop's current row`;
102
+ issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity));
103
+ }
104
+ return issues;
105
+ }
106
+ ////////////////
107
+ byTabix(statement) {
108
+ const children = statement.getChildren();
109
+ for (let i = 0; i < children.length - 1; i++) {
110
+ const child = children[i];
111
+ if (child instanceof token_node_1.TokenNode && child.getFirstToken().getStr().toUpperCase() === "INDEX") {
112
+ return children[i + 1].concatTokens().toUpperCase() === "SY-TABIX";
113
+ }
114
+ }
115
+ return false;
116
+ }
117
+ previousReadsTable(index, statements, table) {
118
+ var _a;
119
+ for (let i = index - 1; i >= 0; i--) {
120
+ const statement = statements[i];
121
+ if (statement.get() instanceof _statement_1.Comment) {
122
+ continue;
123
+ }
124
+ if (!(statement.get() instanceof Statements.ReadTable)) {
125
+ return false;
126
+ }
127
+ const read = (_a = statement.findDirectExpression(Expressions.SimpleSource2)) !== null && _a !== void 0 ? _a : statement.findDirectExpression(Expressions.Source);
128
+ return (read === null || read === void 0 ? void 0 : read.concatTokens().toUpperCase()) === table;
129
+ }
130
+ return false;
131
+ }
132
+ enclosingLoopTables(index, statements) {
133
+ const tables = [];
134
+ let depth = 0;
135
+ for (let i = index - 1; i >= 0; i--) {
136
+ const statement = statements[i];
137
+ const s = statement.get();
138
+ if (s instanceof Statements.EndLoop) {
139
+ depth++;
140
+ }
141
+ else if (s instanceof Statements.Loop) {
142
+ if (depth === 0) {
143
+ const source = statement.findDirectExpression(Expressions.LoopSource);
144
+ if (source !== undefined) {
145
+ tables.push(source.concatTokens().toUpperCase());
146
+ }
147
+ }
148
+ else {
149
+ depth--;
150
+ }
151
+ }
152
+ else if (s instanceof Statements.MethodImplementation
153
+ || s instanceof Statements.Form
154
+ || s instanceof Statements.FunctionModule
155
+ || s instanceof Statements.Module) {
156
+ break;
157
+ }
158
+ }
159
+ return tables;
160
+ }
161
+ }
162
+ exports.DeleteIndexInLoop = DeleteIndexInLoop;
163
+ //# sourceMappingURL=delete_index_in_loop.js.map
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FinalNewline = exports.FinalNewlineConf = void 0;
4
+ const issue_1 = require("../issue");
5
+ const position_1 = require("../position");
6
+ const _basic_rule_config_1 = require("./_basic_rule_config");
7
+ const edit_helper_1 = require("../edit_helper");
8
+ const _irule_1 = require("./_irule");
9
+ const objects_1 = require("../objects");
10
+ class FinalNewlineConf extends _basic_rule_config_1.BasicRuleConfig {
11
+ }
12
+ exports.FinalNewlineConf = FinalNewlineConf;
13
+ class FinalNewline {
14
+ constructor() {
15
+ this.conf = new FinalNewlineConf();
16
+ }
17
+ getMetadata() {
18
+ return {
19
+ key: "final_newline",
20
+ title: "Final newline",
21
+ shortDescription: `Checks that ABAP and XML files end with exactly one newline`,
22
+ extendedInformation: `abapGit serializes every file with exactly one newline at the end. A file without it,
23
+ or with empty lines at the end, is changed again on the next pull and shows up in every diff.
24
+
25
+ Empty files and files containing only line breaks are not checked. A carriage return before the
26
+ newline is ignored, see rule line_break_style. SMIM and W3MI files and XSLT sources are not checked.`,
27
+ tags: [_irule_1.RuleTag.Whitespace, _irule_1.RuleTag.Quickfix, _irule_1.RuleTag.SingleFile],
28
+ badExample: `WRITE 'hello'.`,
29
+ goodExample: `WRITE 'hello'.\n`,
30
+ };
31
+ }
32
+ getConfig() {
33
+ return this.conf;
34
+ }
35
+ setConfig(conf) {
36
+ this.conf = conf;
37
+ }
38
+ initialize(_reg) {
39
+ return this;
40
+ }
41
+ run(obj) {
42
+ const issues = [];
43
+ if (obj instanceof objects_1.MIMEObject || obj instanceof objects_1.WebMIME) {
44
+ return issues;
45
+ }
46
+ for (const file of obj.getFiles()) {
47
+ const filename = file.getFilename();
48
+ if ((filename.endsWith(".abap") || filename.endsWith(".xml")) && !filename.endsWith(".xslt.source.xml")) {
49
+ const issue = this.checkFile(file);
50
+ if (issue) {
51
+ issues.push(issue);
52
+ }
53
+ }
54
+ }
55
+ return issues;
56
+ }
57
+ checkFile(file) {
58
+ const rows = file.getRawRows();
59
+ const last = rows[rows.length - 1];
60
+ if (last !== "") {
61
+ const end = new position_1.Position(rows.length, last.length + 1);
62
+ const fix = edit_helper_1.EditHelper.insertAt(file, end, "\n");
63
+ return issue_1.Issue.atPosition(file, end, "Add newline at end of file", this.getMetadata().key, this.conf.severity, fix);
64
+ }
65
+ let row = rows.length - 2;
66
+ while (row >= 0 && (rows[row] === "" || rows[row] === "\r")) {
67
+ row--;
68
+ }
69
+ if (row < 0 || row === rows.length - 2) {
70
+ return undefined;
71
+ }
72
+ const start = new position_1.Position(row + 2, 1);
73
+ const fix = edit_helper_1.EditHelper.deleteRange(file, start, new position_1.Position(rows.length, 1));
74
+ return issue_1.Issue.atPosition(file, start, "Remove empty lines at end of file", this.getMetadata().key, this.conf.severity, fix);
75
+ }
76
+ }
77
+ exports.FinalNewline = FinalNewline;
78
+ //# sourceMappingURL=final_newline.js.map
@@ -20,6 +20,7 @@ class ForbiddenIdentifier extends _abap_rule_1.ABAPRule {
20
20
  constructor() {
21
21
  super(...arguments);
22
22
  this.conf = new ForbiddenIdentifierConf();
23
+ this.checks = [];
23
24
  }
24
25
  getMetadata() {
25
26
  return {
@@ -39,9 +40,10 @@ https://github.com/abaplint/transpiler/blob/bda94b8b56e2b7f2f87be2168f12361aa530
39
40
  if (this.conf.check === undefined) {
40
41
  this.conf.check = [];
41
42
  }
43
+ this.checks = this.conf.check.map(c => new RegExp(c, "i"));
42
44
  }
43
45
  runParsed(file) {
44
- if (this.conf.check.length === 0) {
46
+ if (this.checks.length === 0) {
45
47
  return [];
46
48
  }
47
49
  let ret = [];
@@ -68,8 +70,7 @@ https://github.com/abaplint/transpiler/blob/bda94b8b56e2b7f2f87be2168f12361aa530
68
70
  check(token, file) {
69
71
  const str = token.getStr();
70
72
  const ret = [];
71
- for (const c of this.conf.check) {
72
- const reg = new RegExp(c, "i");
73
+ for (const reg of this.checks) {
73
74
  if (reg.exec(str)) {
74
75
  const message = "Identifer \"" + str + "\" not allowed";
75
76
  ret.push(issue_1.Issue.atToken(file, token, message, this.getMetadata().key, this.conf.severity));
@@ -22,6 +22,7 @@ exports.ForbiddenVoidTypeConf = ForbiddenVoidTypeConf;
22
22
  class ForbiddenVoidType {
23
23
  constructor() {
24
24
  this.conf = new ForbiddenVoidTypeConf();
25
+ this.checks = [];
25
26
  }
26
27
  getMetadata() {
27
28
  return {
@@ -41,13 +42,14 @@ DATS, TIMS, DATUM, FLAG, INT4, NUMC3, NUMC4, SAP_BOOL, TEXT25, TEXT80, X255, XFE
41
42
  if (this.conf.check === undefined) {
42
43
  this.conf.check = [];
43
44
  }
45
+ this.checks = this.conf.check.map(c => new RegExp(c, "i"));
44
46
  }
45
47
  initialize(reg) {
46
48
  this.reg = reg;
47
49
  return this;
48
50
  }
49
51
  run(obj) {
50
- if (!(obj instanceof _abap_object_1.ABAPObject) || this.conf.check.length === 0) {
52
+ if (!(obj instanceof _abap_object_1.ABAPObject) || this.checks.length === 0) {
51
53
  return [];
52
54
  }
53
55
  return this.traverse(new syntax_1.SyntaxLogic(this.reg, obj).run().spaghetti.getTop());
@@ -90,14 +92,7 @@ DATS, TIMS, DATUM, FLAG, INT4, NUMC3, NUMC4, SAP_BOOL, TEXT25, TEXT80, X255, XFE
90
92
  if (name === undefined) {
91
93
  return false;
92
94
  }
93
- for (const c of this.conf.check) {
94
- const reg = new RegExp(c, "i");
95
- const match = reg.test(name);
96
- if (match === true) {
97
- return true;
98
- }
99
- }
100
- return false;
95
+ return this.checks.some(reg => reg.test(name));
101
96
  }
102
97
  }
103
98
  exports.ForbiddenVoidType = ForbiddenVoidType;
@@ -16,6 +16,9 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./7bit_ascii"), exports);
18
18
  __exportStar(require("./abapdoc"), exports);
19
+ __exportStar(require("./abapdoc_html_tag"), exports);
20
+ __exportStar(require("./abapdoc_leading_at"), exports);
21
+ __exportStar(require("./abapdoc_parameter_names"), exports);
19
22
  __exportStar(require("./add_test_attributes"), exports);
20
23
  __exportStar(require("./aff_and_xml"), exports);
21
24
  __exportStar(require("./align_parameters"), exports);
@@ -38,6 +41,7 @@ __exportStar(require("./cds_naming"), exports);
38
41
  __exportStar(require("./cds_parser_error"), exports);
39
42
  __exportStar(require("./chain_mainly_declarations"), exports);
40
43
  __exportStar(require("./change_if_to_case"), exports);
44
+ __exportStar(require("./changing_sorted_line"), exports);
41
45
  __exportStar(require("./check_abstract"), exports);
42
46
  __exportStar(require("./check_comments"), exports);
43
47
  __exportStar(require("./check_ddic"), exports);
@@ -60,6 +64,7 @@ __exportStar(require("./cyclomatic_complexity"), exports);
60
64
  __exportStar(require("./dangerous_statement"), exports);
61
65
  __exportStar(require("./db_operation_in_loop"), exports);
62
66
  __exportStar(require("./definitions_top"), exports);
67
+ __exportStar(require("./delete_index_in_loop"), exports);
63
68
  __exportStar(require("./description_empty"), exports);
64
69
  __exportStar(require("./double_space"), exports);
65
70
  __exportStar(require("./downport"), exports);
@@ -73,6 +78,7 @@ __exportStar(require("./else_after_all_returns"), exports);
73
78
  __exportStar(require("./exit_or_check"), exports);
74
79
  __exportStar(require("./expand_macros"), exports);
75
80
  __exportStar(require("./exporting"), exports);
81
+ __exportStar(require("./final_newline"), exports);
76
82
  __exportStar(require("./fm_global_parameters_obsolete"), exports);
77
83
  __exportStar(require("./forbidden_identifier"), exports);
78
84
  __exportStar(require("./forbidden_pseudo_and_pragma"), exports);
@@ -96,6 +102,7 @@ __exportStar(require("./in_statement_indentation"), exports);
96
102
  __exportStar(require("./indentation"), exports);
97
103
  __exportStar(require("./index_completely_contained"), exports);
98
104
  __exportStar(require("./inline_data_old_versions"), exports);
105
+ __exportStar(require("./inline_packed_computation"), exports);
99
106
  __exportStar(require("./intf_referencing_clas"), exports);
100
107
  __exportStar(require("./invalid_table_index"), exports);
101
108
  __exportStar(require("./keep_single_parameter_on_one_line"), exports);
@@ -147,6 +154,7 @@ __exportStar(require("./parser_missing_space"), exports);
147
154
  __exportStar(require("./pragma_style"), exports);
148
155
  __exportStar(require("./prefer_corresponding"), exports);
149
156
  __exportStar(require("./prefer_inline"), exports);
157
+ __exportStar(require("./prefer_inline_cast"), exports);
150
158
  __exportStar(require("./prefer_insert_into_table"), exports);
151
159
  __exportStar(require("./prefer_is_not"), exports);
152
160
  __exportStar(require("./prefer_pragmas"), exports);
@@ -159,6 +167,7 @@ __exportStar(require("./prefer_xsdbool"), exports);
159
167
  __exportStar(require("./preferred_compare_operator"), exports);
160
168
  __exportStar(require("./preferred_parameter_ignored"), exports);
161
169
  __exportStar(require("./prefix_is_current_class"), exports);
170
+ __exportStar(require("./range_row_values"), exports);
162
171
  __exportStar(require("./reduce_procedural_code"), exports);
163
172
  __exportStar(require("./reduce_string_templates"), exports);
164
173
  __exportStar(require("./redundant_conversion"), exports);
@@ -175,6 +184,7 @@ __exportStar(require("./short_case"), exports);
175
184
  __exportStar(require("./sicf_consistency"), exports);
176
185
  __exportStar(require("./slow_parameter_passing"), exports);
177
186
  __exportStar(require("./smim_consistency"), exports);
187
+ __exportStar(require("./sort_empty_key"), exports);
178
188
  __exportStar(require("./space_before_colon"), exports);
179
189
  __exportStar(require("./space_before_dot"), exports);
180
190
  __exportStar(require("./sql_escape_host_variables"), exports);
@@ -182,6 +192,7 @@ __exportStar(require("./sql_value_conversion"), exports);
182
192
  __exportStar(require("./start_at_tab"), exports);
183
193
  __exportStar(require("./static_call_via_instance"), exports);
184
194
  __exportStar(require("./strict_sql"), exports);
195
+ __exportStar(require("./subrc_after_assign"), exports);
185
196
  __exportStar(require("./superclass_final"), exports);
186
197
  __exportStar(require("./superfluous_value"), exports);
187
198
  __exportStar(require("./sy_modification"), exports);