@abaplint/core 2.82.15 → 2.83.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.
@@ -1139,6 +1139,7 @@ declare class DataElement extends AbstractObject {
1139
1139
  allowNamespace: boolean;
1140
1140
  };
1141
1141
  setDirty(): void;
1142
+ getDomainName(): string | undefined;
1142
1143
  parseType(reg: IRegistry): AbstractType;
1143
1144
  parse(): {
1144
1145
  updated: boolean;
@@ -1177,7 +1178,7 @@ declare class DDIC {
1177
1178
  lookupNoVoid(name: string): ILookupResult | undefined;
1178
1179
  /** lookup with voiding and unknown types */
1179
1180
  lookup(name: string): ILookupResult;
1180
- lookupDomain(name: string): ILookupResult;
1181
+ lookupDomain(name: string, parent?: string): ILookupResult;
1181
1182
  lookupDataElement(name: string | undefined): ILookupResult;
1182
1183
  lookupTableOrView(name: string | undefined): ILookupResult;
1183
1184
  lookupTableOrView2(name: string | undefined): Table | DataDefinition | View | undefined;
@@ -1358,7 +1359,7 @@ declare class Domain extends AbstractObject {
1358
1359
  allowNamespace: boolean;
1359
1360
  };
1360
1361
  setDirty(): void;
1361
- parseType(reg: IRegistry): AbstractType;
1362
+ parseType(reg: IRegistry, parent?: string): AbstractType;
1362
1363
  parse(): {
1363
1364
  updated: boolean;
1364
1365
  runtime: number;
@@ -2572,10 +2573,14 @@ declare interface IGlobalConfig {
2572
2573
  useApackDependencies?: boolean;
2573
2574
  /** Do not report any issues for includes without main programs */
2574
2575
  skipIncludesWithoutMain?: boolean;
2575
- /** list of files to exclude, case insensitive regex
2576
+ /** list of files to exclude, these files are not added when running syntax check or any other rules, case insensitive regex
2576
2577
  * @uniqueItems true
2577
2578
  */
2578
2579
  exclude?: string[];
2580
+ /** list of files to not report any issues for, case insensitive regex
2581
+ * @uniqueItems true
2582
+ */
2583
+ noIssues?: string[];
2579
2584
  }
2580
2585
 
2581
2586
  declare interface IImplementing {
@@ -9,7 +9,7 @@ class CallFunction {
9
9
  const starting = (0, combi_1.seq)("STARTING NEW TASK", expressions_1.SimpleSource2);
10
10
  const update = (0, combi_1.str)("IN UPDATE TASK");
11
11
  const unit = (0, combi_1.seq)("UNIT", expressions_1.Source);
12
- const background = (0, combi_1.seq)("IN BACKGROUND", (0, combi_1.alt)("TASK", unit));
12
+ const background = (0, combi_1.verNot)(version_1.Version.Cloud, (0, combi_1.seq)("IN BACKGROUND", (0, combi_1.alt)("TASK", unit)));
13
13
  const calling = (0, combi_1.seq)("CALLING", expressions_1.MethodName, "ON END OF TASK");
14
14
  const performing = (0, combi_1.seq)("PERFORMING", expressions_1.FormName, "ON END OF TASK");
15
15
  const separate = (0, combi_1.str)("AS SEPARATE UNIT");
package/build/src/ddic.js CHANGED
@@ -185,10 +185,10 @@ class DDIC {
185
185
  return { type: new Types.VoidType(name) };
186
186
  }
187
187
  }
188
- lookupDomain(name) {
188
+ lookupDomain(name, parent) {
189
189
  const found = this.reg.getObject("DOMA", name);
190
190
  if (found) {
191
- return { type: found.parseType(this.reg), object: found };
191
+ return { type: found.parseType(this.reg, parent), object: found };
192
192
  }
193
193
  else if (this.reg.inErrorNamespace(name)) {
194
194
  return { type: new Types.UnknownType(name + ", lookupDomain"), object: undefined };
@@ -26,6 +26,11 @@ class DataElement extends _abstract_object_1.AbstractObject {
26
26
  this.parsedXML = undefined;
27
27
  super.setDirty();
28
28
  }
29
+ getDomainName() {
30
+ var _a;
31
+ this.parse();
32
+ return (_a = this.parsedXML) === null || _a === void 0 ? void 0 : _a.domname;
33
+ }
29
34
  parseType(reg) {
30
35
  const references = [];
31
36
  let lookup = undefined;
@@ -39,7 +44,7 @@ class DataElement extends _abstract_object_1.AbstractObject {
39
44
  lookup = { type: new Types.UnknownType("DOMNAME unexpectely empty in " + this.getName()) };
40
45
  }
41
46
  else {
42
- lookup = ddic.lookupDomain(this.parsedXML.domname);
47
+ lookup = ddic.lookupDomain(this.parsedXML.domname, this.getName());
43
48
  }
44
49
  }
45
50
  else if (this.parsedXML.refkind === "R") {
@@ -24,7 +24,7 @@ class Domain extends _abstract_object_1.AbstractObject {
24
24
  this.parsedType = undefined;
25
25
  super.setDirty();
26
26
  }
27
- parseType(reg) {
27
+ parseType(reg, parent) {
28
28
  if (this.parsedType) {
29
29
  return this.parsedType;
30
30
  }
@@ -32,7 +32,7 @@ class Domain extends _abstract_object_1.AbstractObject {
32
32
  return new Types.UnknownType("Domain " + this.getName() + " parser error", this.getName());
33
33
  }
34
34
  const ddic = new ddic_1.DDIC(reg);
35
- this.parsedType = ddic.textToType(this.parsedXML.datatype, this.parsedXML.length, this.parsedXML.decimals, this.getName());
35
+ this.parsedType = ddic.textToType(this.parsedXML.datatype, this.parsedXML.length, this.parsedXML.decimals, parent || this.getName(), parent !== undefined);
36
36
  return this.parsedType;
37
37
  }
38
38
  parse() {
@@ -175,7 +175,7 @@ class Table extends _abstract_object_1.AbstractObject {
175
175
  const length = field.LENG ? field.LENG : field.INTLEN;
176
176
  components.push({
177
177
  name: field.FIELDNAME,
178
- type: ddic.textToType(datatype, length, field.DECIMALS, this.getName())
178
+ type: ddic.textToType(datatype, length, field.DECIMALS, this.getName() + "-" + field.FIELDNAME)
179
179
  });
180
180
  }
181
181
  else {
@@ -68,7 +68,7 @@ class Registry {
68
68
  }
69
69
  static abaplintVersion() {
70
70
  // magic, see build script "version.sh"
71
- return "2.82.15";
71
+ return "2.83.1";
72
72
  }
73
73
  getDDICReferences() {
74
74
  return this.references;
@@ -326,10 +326,23 @@ class Registry {
326
326
  excludeIssues(issues) {
327
327
  var _a;
328
328
  const ret = issues;
329
+ const globalNoIssues = this.conf.getGlobal().noIssues || [];
330
+ const globalNoIssuesPatterns = globalNoIssues.map(x => new RegExp(x, "i"));
331
+ if (globalNoIssuesPatterns.length > 0) {
332
+ for (let i = ret.length - 1; i >= 0; i--) {
333
+ const filename = ret[i].getFilename();
334
+ if (excludeHelper_1.ExcludeHelper.isExcluded(filename, globalNoIssuesPatterns)) {
335
+ ret.splice(i, 1);
336
+ }
337
+ }
338
+ }
329
339
  // exclude issues, as now we know both the filename and issue key
330
340
  for (const rule of artifacts_rules_1.ArtifactsRules.getRules()) {
331
341
  const key = rule.getMetadata().key;
332
- const ruleExclude = ((_a = this.conf.readByKey(key, "exclude")) !== null && _a !== void 0 ? _a : []);
342
+ const ruleExclude = (_a = this.conf.readByKey(key, "exclude")) !== null && _a !== void 0 ? _a : [];
343
+ if (ruleExclude.length === 0) {
344
+ continue;
345
+ }
333
346
  const ruleExcludePatterns = ruleExclude.map(x => new RegExp(x, "i"));
334
347
  for (let i = ret.length - 1; i >= 0; i--) {
335
348
  if (ret[i].getKey() !== key) {
@@ -4,6 +4,7 @@ exports.ImplementMethods = exports.ImplementMethodsConf = void 0;
4
4
  const issue_1 = require("../issue");
5
5
  const _abap_rule_1 = require("./_abap_rule");
6
6
  const _basic_rule_config_1 = require("./_basic_rule_config");
7
+ const objects_1 = require("../objects");
7
8
  const Statements = require("../abap/2_statements/statements");
8
9
  const Expressions = require("../abap/2_statements/expressions");
9
10
  const _irule_1 = require("./_irule");
@@ -22,6 +23,7 @@ class ImplementMethods extends _abap_rule_1.ABAPRule {
22
23
  key: "implement_methods",
23
24
  title: "Implement methods",
24
25
  shortDescription: `Checks for abstract methods and methods from interfaces which need implementing.`,
26
+ extendedInformation: `INCLUDE programs are only checked in connection with their main programs.`,
25
27
  tags: [_irule_1.RuleTag.Syntax, _irule_1.RuleTag.Quickfix],
26
28
  };
27
29
  }
@@ -36,6 +38,9 @@ class ImplementMethods extends _abap_rule_1.ABAPRule {
36
38
  if (file.getStructure() === undefined) {
37
39
  return [];
38
40
  }
41
+ else if (obj instanceof objects_1.Program && obj.isInclude() === true) {
42
+ return [];
43
+ }
39
44
  this.obj = obj;
40
45
  for (const classDefinition of file.getInfo().listClassDefinitions()) {
41
46
  const classImplementation = this.lookupImplementationInObject(classDefinition.name, obj);
@@ -92,6 +92,7 @@ __exportStar(require("./msag_consistency"), exports);
92
92
  __exportStar(require("./names_no_dash"), exports);
93
93
  __exportStar(require("./nesting"), exports);
94
94
  __exportStar(require("./newline_between_methods"), exports);
95
+ __exportStar(require("./no_aliases"), exports);
95
96
  __exportStar(require("./no_chained_assignment"), exports);
96
97
  __exportStar(require("./no_public_attributes"), exports);
97
98
  __exportStar(require("./no_yoda_conditions"), exports);
@@ -103,6 +104,7 @@ __exportStar(require("./parser_702_chaining"), exports);
103
104
  __exportStar(require("./parser_error"), exports);
104
105
  __exportStar(require("./parser_missing_space"), exports);
105
106
  __exportStar(require("./pragma_placement"), exports);
107
+ __exportStar(require("./prefer_corresponding"), exports);
106
108
  __exportStar(require("./prefer_inline"), exports);
107
109
  __exportStar(require("./prefer_is_not"), exports);
108
110
  __exportStar(require("./prefer_raise_exception_new"), exports);
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NoAliases = exports.NoAliasesConf = void 0;
4
+ const issue_1 = require("../issue");
5
+ const _basic_rule_config_1 = require("./_basic_rule_config");
6
+ const _abap_rule_1 = require("./_abap_rule");
7
+ const Statements = require("../abap/2_statements/statements");
8
+ const _irule_1 = require("./_irule");
9
+ class NoAliasesConf extends _basic_rule_config_1.BasicRuleConfig {
10
+ }
11
+ exports.NoAliasesConf = NoAliasesConf;
12
+ class NoAliases extends _abap_rule_1.ABAPRule {
13
+ constructor() {
14
+ super(...arguments);
15
+ this.conf = new NoAliasesConf();
16
+ }
17
+ getMetadata() {
18
+ return {
19
+ key: "no_aliases",
20
+ title: "No ALIASES",
21
+ shortDescription: `Detects use of the ALIAS statement`,
22
+ tags: [_irule_1.RuleTag.SingleFile],
23
+ };
24
+ }
25
+ getConfig() {
26
+ return this.conf;
27
+ }
28
+ setConfig(conf) {
29
+ this.conf = conf;
30
+ }
31
+ runParsed(file) {
32
+ const issues = [];
33
+ const message = "Do not use ALIASES";
34
+ for (const stat of file.getStatements()) {
35
+ if (stat.get() instanceof Statements.Aliases) {
36
+ issues.push(issue_1.Issue.atStatement(file, stat, message, this.getMetadata().key, this.conf.severity));
37
+ }
38
+ }
39
+ return issues;
40
+ }
41
+ }
42
+ exports.NoAliases = NoAliases;
43
+ //# sourceMappingURL=no_aliases.js.map
@@ -63,6 +63,8 @@ class ObsoleteStatementConf extends _basic_rule_config_1.BasicRuleConfig {
63
63
  this.callTransformation = true;
64
64
  /** Check for POSIX REGEX usage */
65
65
  this.regex = true;
66
+ /** Check for OCCURENCES vs OCCURRENCES usage */
67
+ this.occurences = true;
66
68
  }
67
69
  }
68
70
  exports.ObsoleteStatementConf = ObsoleteStatementConf;
@@ -113,7 +115,9 @@ SORT BY FS: https://help.sap.com/doc/abapdocu_752_index_htm/7.52/en-US/abapsort_
113
115
 
114
116
  CALL TRANSFORMATION OBJECTS: https://help.sap.com/doc/abapdocu_752_index_htm/7.52/en-US/abapcall_transformation_objects.htm
115
117
 
116
- POSIX REGEX: https://help.sap.com/doc/abapdocu_755_index_htm/7.55/en-US/index.htm`,
118
+ POSIX REGEX: https://help.sap.com/doc/abapdocu_755_index_htm/7.55/en-US/index.htm
119
+
120
+ OCCURENCES: check for OCCURENCES vs OCCURRENCES`,
117
121
  };
118
122
  }
119
123
  getConfig() {
@@ -270,6 +274,13 @@ POSIX REGEX: https://help.sap.com/doc/abapdocu_755_index_htm/7.55/en-US/index.ht
270
274
  issues.push(issue);
271
275
  }
272
276
  }
277
+ if (this.conf.occurences && sta instanceof Statements.Replace) {
278
+ const concat = staNode.concatTokens().toUpperCase();
279
+ if (concat.includes(" OCCURENCES ")) {
280
+ const issue = issue_1.Issue.atStatement(file, staNode, "Use \"OCCURRENCES\"", this.getMetadata().key, this.conf.severity);
281
+ issues.push(issue);
282
+ }
283
+ }
273
284
  if (configVersion >= version_1.Version.v756 && this.conf.regex) {
274
285
  if (sta instanceof Statements.Find || sta instanceof Statements.Replace) {
275
286
  if ((_c = staNode.findFirstExpression(Expressions.FindType)) === null || _c === void 0 ? void 0 : _c.concatTokens().includes("REGEX")) {
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PreferCorresponding = exports.PreferCorrespondingConf = void 0;
4
+ const issue_1 = require("../issue");
5
+ const _basic_rule_config_1 = require("./_basic_rule_config");
6
+ const _abap_rule_1 = require("./_abap_rule");
7
+ const Statements = require("../abap/2_statements/statements");
8
+ const _irule_1 = require("./_irule");
9
+ const version_1 = require("../version");
10
+ class PreferCorrespondingConf extends _basic_rule_config_1.BasicRuleConfig {
11
+ }
12
+ exports.PreferCorrespondingConf = PreferCorrespondingConf;
13
+ class PreferCorresponding extends _abap_rule_1.ABAPRule {
14
+ constructor() {
15
+ super(...arguments);
16
+ this.conf = new PreferCorrespondingConf();
17
+ }
18
+ getMetadata() {
19
+ return {
20
+ key: "prefer_corresponding",
21
+ title: "Prefer corresponding( ) to MOVE-CORRESPONDING",
22
+ shortDescription: `Prefer corresponding( ) to MOVE-CORRESPONDING, from v740sp05 and up`,
23
+ tags: [_irule_1.RuleTag.SingleFile, _irule_1.RuleTag.Upport],
24
+ };
25
+ }
26
+ getConfig() {
27
+ return this.conf;
28
+ }
29
+ setConfig(conf) {
30
+ this.conf = conf;
31
+ }
32
+ runParsed(file) {
33
+ const issues = [];
34
+ if (this.reg.getConfig().getVersion() < version_1.Version.v740sp05) {
35
+ return issues;
36
+ }
37
+ const message = "Use CORRESPONDING type( ... ) instead";
38
+ for (const stat of file.getStatements()) {
39
+ if (stat.get() instanceof Statements.MoveCorresponding
40
+ && stat.getChildren().length === 7) {
41
+ issues.push(issue_1.Issue.atStatement(file, stat, message, this.getMetadata().key, this.conf.severity));
42
+ }
43
+ }
44
+ return issues;
45
+ }
46
+ }
47
+ exports.PreferCorresponding = PreferCorresponding;
48
+ //# sourceMappingURL=prefer_corresponding.js.map
@@ -41,7 +41,7 @@ If the target is a sorted/hashed table, no issue is reported`,
41
41
  this.conf = conf;
42
42
  }
43
43
  run(obj) {
44
- var _a, _b, _c;
44
+ var _a;
45
45
  const issues = [];
46
46
  if (!(obj instanceof _abap_object_1.ABAPObject) || obj.getType() === "INTF") {
47
47
  return [];
@@ -67,21 +67,36 @@ If the target is a sorted/hashed table, no issue is reported`,
67
67
  else if (s.findFirstExpression(Expressions.SQLOrderBy)) {
68
68
  continue;
69
69
  }
70
- const target = (_b = s.findFirstExpression(Expressions.SQLIntoTable)) === null || _b === void 0 ? void 0 : _b.findFirstExpression(Expressions.Target);
71
- if (target) {
72
- const start = target.getFirstToken().getStart();
73
- const scope = spaghetti.lookupPosition(start, file.getFilename());
74
- const type = (_c = scope === null || scope === void 0 ? void 0 : scope.findWriteReference(start)) === null || _c === void 0 ? void 0 : _c.getType();
75
- if (type instanceof basic_1.TableType
76
- && ((type === null || type === void 0 ? void 0 : type.getAccessType()) === basic_1.TableAccessType.sorted || (type === null || type === void 0 ? void 0 : type.getAccessType()) === basic_1.TableAccessType.hashed)) {
77
- continue;
78
- }
70
+ if (this.isTargetSortedOrHashed(s, spaghetti, file)) {
71
+ continue;
79
72
  }
80
73
  issues.push(issue_1.Issue.atStatement(file, s, "Add ORDER BY", this.getMetadata().key, this.conf.severity));
81
74
  }
82
75
  }
83
76
  return issues;
84
77
  }
78
+ isTargetSortedOrHashed(s, spaghetti, file) {
79
+ var _a, _b;
80
+ const target = (_a = s.findFirstExpression(Expressions.SQLIntoTable)) === null || _a === void 0 ? void 0 : _a.findFirstExpression(Expressions.Target);
81
+ if (target) {
82
+ const start = target.getFirstToken().getStart();
83
+ const scope = spaghetti.lookupPosition(start, file.getFilename());
84
+ let type = (_b = scope === null || scope === void 0 ? void 0 : scope.findWriteReference(start)) === null || _b === void 0 ? void 0 : _b.getType();
85
+ const children = target.getChildren();
86
+ if (type instanceof basic_1.StructureType && children.length >= 3 && children[1].concatTokens() === "-") {
87
+ const found = type.getComponentByName(children[2].concatTokens());
88
+ if (found === undefined) {
89
+ return false;
90
+ }
91
+ type = found;
92
+ }
93
+ if (type instanceof basic_1.TableType
94
+ && ((type === null || type === void 0 ? void 0 : type.getAccessType()) === basic_1.TableAccessType.sorted || (type === null || type === void 0 ? void 0 : type.getAccessType()) === basic_1.TableAccessType.hashed)) {
95
+ return true;
96
+ }
97
+ }
98
+ return false;
99
+ }
85
100
  }
86
101
  exports.SelectAddOrderBy = SelectAddOrderBy;
87
102
  //# sourceMappingURL=select_add_order_by.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/core",
3
- "version": "2.82.15",
3
+ "version": "2.83.1",
4
4
  "description": "abaplint - Core API",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/abaplint.d.ts",
@@ -45,17 +45,17 @@
45
45
  },
46
46
  "homepage": "https://abaplint.org",
47
47
  "devDependencies": {
48
- "@microsoft/api-extractor": "^7.18.21",
49
- "@types/chai": "^4.2.22",
48
+ "@microsoft/api-extractor": "^7.19.2",
49
+ "@types/chai": "^4.3.0",
50
50
  "@types/mocha": "^9.0.0",
51
- "@types/node": "^16.11.12",
51
+ "@types/node": "^17.0.1",
52
52
  "chai": "^4.3.4",
53
- "eslint": "^8.4.1",
53
+ "eslint": "^8.5.0",
54
54
  "mocha": "^9.1.3",
55
55
  "c8": "^7.10.0",
56
56
  "source-map-support": "^0.5.21",
57
57
  "ts-json-schema-generator": "^0.97.0",
58
- "typescript": "^4.5.2"
58
+ "typescript": "^4.5.4"
59
59
  },
60
60
  "dependencies": {
61
61
  "fast-xml-parser": "^3.21.1",