@abaplint/core 2.78.12 → 2.79.2

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.
@@ -1350,6 +1350,13 @@ declare class Domain extends AbstractObject {
1350
1350
  updated: boolean;
1351
1351
  runtime: number;
1352
1352
  };
1353
+ getFixedValues(): DomainValue[];
1354
+ }
1355
+
1356
+ declare interface DomainValue {
1357
+ language: string;
1358
+ value: string;
1359
+ description: string;
1353
1360
  }
1354
1361
 
1355
1362
  declare class Dynamic extends Expression {
@@ -2628,6 +2635,7 @@ declare namespace Info {
2628
2635
  InfoMethodParameter,
2629
2636
  InfoMethodDefinition,
2630
2637
  InfoInterfaceDefinition,
2638
+ InfoConstant,
2631
2639
  InfoAlias,
2632
2640
  InfoImplementing,
2633
2641
  InfoClassDefinition,
@@ -2667,6 +2675,14 @@ declare interface InfoClassImplementation {
2667
2675
  methods: readonly Identifier[];
2668
2676
  }
2669
2677
 
2678
+ declare interface InfoConstant {
2679
+ identifier: Identifier;
2680
+ name: string;
2681
+ typeName: string;
2682
+ visibility: Visibility;
2683
+ value: string;
2684
+ }
2685
+
2670
2686
  declare interface InfoFormDefinition {
2671
2687
  name: string;
2672
2688
  identifier: Identifier;
@@ -2688,6 +2704,7 @@ declare interface InfoInterfaceDefinition {
2688
2704
  interfaces: readonly InfoImplementing[];
2689
2705
  methods: readonly InfoMethodDefinition[];
2690
2706
  aliases: readonly InfoAlias[];
2707
+ constants: readonly InfoConstant[];
2691
2708
  attributes: readonly InfoAttribute[];
2692
2709
  }
2693
2710
 
@@ -3646,6 +3663,7 @@ declare namespace Objects {
3646
3663
  DataElement,
3647
3664
  DialogModule,
3648
3665
  Documentation,
3666
+ DomainValue,
3649
3667
  Domain,
3650
3668
  EcattTestConfiguration,
3651
3669
  EcattTestDataContainer,
@@ -5660,6 +5678,7 @@ export declare enum Version {
5660
5678
  v753 = "v753",
5661
5679
  v754 = "v754",
5662
5680
  v755 = "v755",
5681
+ v756 = "v756",
5663
5682
  Cloud = "Cloud"
5664
5683
  }
5665
5684
 
@@ -76,7 +76,7 @@ class ABAPFileInformation {
76
76
  this.implementations.push({
77
77
  name: name.getStr(),
78
78
  identifier: new _identifier_1.Identifier(name, this.filename),
79
- methods
79
+ methods,
80
80
  });
81
81
  }
82
82
  for (const statement of structure.findAllStructures(Structures.Form)) {
@@ -100,6 +100,7 @@ class ABAPFileInformation {
100
100
  const methods = this.parseMethodDefinition(found, visibility_1.Visibility.Public);
101
101
  const attributes = this.parseAttributes(found, visibility_1.Visibility.Public);
102
102
  const aliases = this.parseAliases(found, visibility_1.Visibility.Public);
103
+ const constants = this.parseConstants(found, visibility_1.Visibility.Public);
103
104
  const g = i.findDirectExpression(Expressions.ClassGlobal);
104
105
  this.interfaces.push({
105
106
  name: interfaceName.getStr(),
@@ -109,6 +110,7 @@ class ABAPFileInformation {
109
110
  interfaces: this.getImplementing(found),
110
111
  aliases,
111
112
  methods,
113
+ constants,
112
114
  attributes,
113
115
  });
114
116
  }
@@ -126,6 +128,9 @@ class ABAPFileInformation {
126
128
  const aliases = this.parseAliases(found.findFirstStructure(Structures.PublicSection), visibility_1.Visibility.Public);
127
129
  aliases.push(...this.parseAliases(found.findFirstStructure(Structures.ProtectedSection), visibility_1.Visibility.Protected));
128
130
  aliases.push(...this.parseAliases(found.findFirstStructure(Structures.PrivateSection), visibility_1.Visibility.Private));
131
+ const constants = this.parseConstants(found.findFirstStructure(Structures.PublicSection), visibility_1.Visibility.Public);
132
+ constants.push(...this.parseConstants(found.findFirstStructure(Structures.ProtectedSection), visibility_1.Visibility.Protected));
133
+ constants.push(...this.parseConstants(found.findFirstStructure(Structures.PrivateSection), visibility_1.Visibility.Private));
129
134
  const superClassName = (_a = found.findFirstExpression(Expressions.SuperClassName)) === null || _a === void 0 ? void 0 : _a.getFirstToken().getStr();
130
135
  const containsGlobal = found.findFirstExpression(Expressions.ClassGlobal);
131
136
  const concat = found.findFirstStatement(Statements.ClassDefinition).concatTokens().toUpperCase();
@@ -142,6 +147,7 @@ class ABAPFileInformation {
142
147
  isFinal: found.findFirstExpression(Expressions.ClassFinal) !== undefined,
143
148
  aliases,
144
149
  attributes,
150
+ constants,
145
151
  });
146
152
  }
147
153
  }
@@ -194,6 +200,29 @@ class ABAPFileInformation {
194
200
  }
195
201
  return ret;
196
202
  }
203
+ parseConstants(node, visibility) {
204
+ var _a, _b;
205
+ if (node === undefined) {
206
+ return [];
207
+ }
208
+ const results = [];
209
+ for (const constant of node.findAllStatements(Statements.Constant)) {
210
+ const name = constant.findFirstExpression(Expressions.DefinitionName).getFirstToken();
211
+ const typeName = constant.findFirstExpression(Expressions.TypeName);
212
+ // VALUE `const_value` -> `const_value`
213
+ const literal = (_b = (_a = constant.findFirstExpression(Expressions.Value)) === null || _a === void 0 ? void 0 : _a.getTokens()[1].getStr()) !== null && _b !== void 0 ? _b : "``";
214
+ // `const_value` -> const_value
215
+ const value = literal.slice(1, (literal === null || literal === void 0 ? void 0 : literal.length) - 1);
216
+ results.push({
217
+ name: name.getStr(),
218
+ typeName: typeName ? typeName.getFirstToken().getStr() : "",
219
+ value: value,
220
+ identifier: new _identifier_1.Identifier(name, this.filename),
221
+ visibility,
222
+ });
223
+ }
224
+ return results;
225
+ }
197
226
  parseAttributes(node, visibility) {
198
227
  if (node === undefined) {
199
228
  return [];
@@ -20,6 +20,7 @@ class TypeUtils {
20
20
  || type instanceof basic_1.AnyType
21
21
  || type instanceof basic_1.UnknownType
22
22
  || type instanceof basic_1.NumericType
23
+ || type instanceof basic_1.CSequenceType
23
24
  || type instanceof basic_1.DateType
24
25
  || type instanceof basic_1.CLikeType
25
26
  || type instanceof basic_1.PackedType
@@ -18,6 +18,12 @@ class FieldAssignment {
18
18
  let type = undefined;
19
19
  if (targetType instanceof basic_1.StructureType) {
20
20
  type = targetType.getComponentByName(name);
21
+ if (type === undefined && targetType.containsVoid() === false) {
22
+ throw new Error(`field ${name} does not exist in structure`);
23
+ }
24
+ }
25
+ else if (targetType instanceof basic_1.VoidType) {
26
+ type = targetType;
21
27
  }
22
28
  new source_1.Source().runSyntax(s, scope, filename, type);
23
29
  }
@@ -70,7 +70,7 @@ class SemanticHighlighting {
70
70
  || statementInstance instanceof Statements.MethodImplementation
71
71
  || statementInstance instanceof Statements.EndMethod
72
72
  || statementInstance instanceof Statements.EndClass
73
- || statementInstance instanceof Statements.InterfaceDef
73
+ || statementInstance instanceof Statements.Interface
74
74
  || statementInstance instanceof Statements.EndInterface
75
75
  || statementInstance instanceof Statements.Form
76
76
  || statementInstance instanceof Statements.EndForm) {
@@ -35,7 +35,7 @@ class Domain extends _abstract_object_1.AbstractObject {
35
35
  return this.parsedType;
36
36
  }
37
37
  parse() {
38
- var _a, _b, _c;
38
+ var _a, _b, _c, _d, _e, _f, _g;
39
39
  if (this.parsedXML) {
40
40
  return { updated: false, runtime: 0 };
41
41
  }
@@ -46,15 +46,32 @@ class Domain extends _abstract_object_1.AbstractObject {
46
46
  return { updated: false, runtime: 0 };
47
47
  }
48
48
  const dd01v = (_c = (_b = (_a = parsed.abapGit) === null || _a === void 0 ? void 0 : _a["asx:abap"]) === null || _b === void 0 ? void 0 : _b["asx:values"]) === null || _c === void 0 ? void 0 : _c.DD01V;
49
+ const dd07v_tab = (_g = (_f = (_e = (_d = parsed.abapGit) === null || _d === void 0 ? void 0 : _d["asx:abap"]) === null || _e === void 0 ? void 0 : _e["asx:values"]) === null || _f === void 0 ? void 0 : _f.DD07V_TAB) === null || _g === void 0 ? void 0 : _g.DD07V;
50
+ const values = [];
51
+ if (dd07v_tab) {
52
+ for (const ddo7v of dd07v_tab) {
53
+ const value = {
54
+ description: ddo7v === null || ddo7v === void 0 ? void 0 : ddo7v.DDTEXT,
55
+ value: ddo7v === null || ddo7v === void 0 ? void 0 : ddo7v.DOMVALUE_L,
56
+ language: ddo7v === null || ddo7v === void 0 ? void 0 : ddo7v.DDLANGUAGE,
57
+ };
58
+ values.push(value);
59
+ }
60
+ }
49
61
  this.parsedXML = {
50
62
  description: dd01v === null || dd01v === void 0 ? void 0 : dd01v.DDTEXT,
51
63
  datatype: dd01v === null || dd01v === void 0 ? void 0 : dd01v.DATATYPE,
52
64
  length: dd01v === null || dd01v === void 0 ? void 0 : dd01v.LENG,
53
65
  decimals: dd01v === null || dd01v === void 0 ? void 0 : dd01v.DECIMALS,
66
+ values: values,
54
67
  };
55
68
  const end = Date.now();
56
69
  return { updated: true, runtime: end - start };
57
70
  }
71
+ getFixedValues() {
72
+ var _a, _b;
73
+ return (_b = (_a = this.parsedXML) === null || _a === void 0 ? void 0 : _a.values) !== null && _b !== void 0 ? _b : [];
74
+ }
58
75
  }
59
76
  exports.Domain = Domain;
60
77
  //# sourceMappingURL=domain.js.map
@@ -68,7 +68,7 @@ class Registry {
68
68
  }
69
69
  static abaplintVersion() {
70
70
  // magic, see build script "version.sh"
71
- return "2.78.12";
71
+ return "2.79.2";
72
72
  }
73
73
  getDDICReferences() {
74
74
  return this.references;
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConstantClasses = exports.ConstantClassesConf = 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
+ const __1 = require("..");
8
+ /** Checks that constants classes are in sync with domain fixed values */
9
+ class ConstantClassesConf extends _basic_rule_config_1.BasicRuleConfig {
10
+ }
11
+ exports.ConstantClassesConf = ConstantClassesConf;
12
+ class ConstantClasses {
13
+ constructor() {
14
+ this.conf = new ConstantClassesConf();
15
+ }
16
+ getMetadata() {
17
+ return {
18
+ key: "constant_classes",
19
+ title: "Validate constant classes",
20
+ shortDescription: `Checks that a class contains exactly the constants corresponding to a domain's fixed values.`,
21
+ extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#prefer-enumeration-classes-to-constants-interfaces`,
22
+ tags: [_irule_1.RuleTag.Syntax, _irule_1.RuleTag.Styleguide, _irule_1.RuleTag.Experimental],
23
+ };
24
+ }
25
+ initialize(reg) {
26
+ this.reg = reg;
27
+ return this;
28
+ }
29
+ getConfig() {
30
+ return this.conf;
31
+ }
32
+ setConfig(conf) {
33
+ this.conf = conf;
34
+ }
35
+ run(obj) {
36
+ if (this.conf
37
+ && this.conf.mapping
38
+ && obj instanceof __1.Objects.Domain) {
39
+ const configEntry = this.conf.mapping.find(x => x.domain.toUpperCase() === obj.getName().toUpperCase());
40
+ if (!configEntry) {
41
+ return [];
42
+ }
43
+ const classWithConstants = this.reg.getObject("CLAS", configEntry === null || configEntry === void 0 ? void 0 : configEntry.class.toUpperCase());
44
+ if (!classWithConstants) {
45
+ return [issue_1.Issue.atIdentifier(obj.getIdentifier(), `Constant class pattern implementation ${configEntry.class} missing for domain ${configEntry.domain}`, this.getMetadata().key, this.conf.severity)];
46
+ // quickfix will implement the whole class
47
+ }
48
+ const classContents = classWithConstants.getMainABAPFile();
49
+ if (classContents === undefined) {
50
+ return [];
51
+ }
52
+ const def = classWithConstants.getClassDefinition();
53
+ if (!def) {
54
+ // this issue is checked by rule implement_methods.
55
+ // we will not issue errors that all constants are missing until there is a class implementation
56
+ return [];
57
+ }
58
+ const domainValueInfo = obj.getFixedValues();
59
+ const domainValues = domainValueInfo.map(x => x.value);
60
+ const issues = [];
61
+ if (obj.getFixedValues().length === 0) {
62
+ // possibly this is not even a domain with fixed values
63
+ issues.push(issue_1.Issue.atStatement(classContents, classContents.getStatements()[0], `Domain ${configEntry.domain} does not contain any fixed values. Either add some values or disable this check`, this.getMetadata().key, this.conf.severity));
64
+ }
65
+ // later we will raise an issue if we did not find it
66
+ let domainNameConstantFound = false;
67
+ for (const constant of def.constants) {
68
+ if (configEntry.constantForDomainName
69
+ && constant.name === configEntry.constantForDomainName) {
70
+ // we require the constant value to be uppercase just in case
71
+ // in the config it does not matter
72
+ if (constant.value !== configEntry.domain.toLocaleUpperCase()) {
73
+ issues.push(this.issueAtConstant(constant, `Constant value ${constant.value} must match domain name ${configEntry.domain} `));
74
+ }
75
+ domainNameConstantFound = true;
76
+ continue;
77
+ }
78
+ if (configEntry.useExactType && constant.typeName.toLowerCase() !== configEntry.domain.toLowerCase()) {
79
+ issues.push(this.issueAtConstant(constant, `Use exact type ${configEntry.domain} instead of ${constant.typeName}`));
80
+ // quickfix will change the type
81
+ }
82
+ if (constant.visibility !== __1.Visibility.Public) {
83
+ issues.push(this.issueAtConstant(constant, `Constant ${constant.name} should be public`));
84
+ // quickfix will move constant
85
+ }
86
+ if (!domainValues.includes(constant.value)) {
87
+ issues.push(this.issueAtConstant(constant, `Extra constant ${constant.name} found which is not present in domain ${configEntry.domain}`));
88
+ // quickfix will remove constant
89
+ }
90
+ }
91
+ for (const d of domainValueInfo) {
92
+ if (!def.constants.find(c => c.value === d.value)) {
93
+ issues.push(issue_1.Issue.atStatement(classContents, classContents.getStatements()[0], `Missing constant for ${d.value} (domain ${configEntry.domain})`, this.getMetadata().key, this.conf.severity));
94
+ // quickfix will add constant
95
+ }
96
+ }
97
+ if (configEntry.constantForDomainName && !domainNameConstantFound) {
98
+ issues.push(issue_1.Issue.atStatement(classContents, classContents.getStatements()[0], `Missing constant ${configEntry.constantForDomainName} for name of domain ${configEntry.domain}`, this.getMetadata().key, this.conf.severity));
99
+ }
100
+ return issues;
101
+ }
102
+ return [];
103
+ }
104
+ issueAtConstant(constant, message) {
105
+ return issue_1.Issue.atIdentifier(constant.identifier, message, this.getMetadata().key, this.conf.severity);
106
+ }
107
+ }
108
+ exports.ConstantClasses = ConstantClasses;
109
+ //# sourceMappingURL=constant_classes.js.map
@@ -142,4 +142,5 @@ __exportStar(require("./use_new"), exports);
142
142
  __exportStar(require("./when_others_last"), exports);
143
143
  __exportStar(require("./whitespace_end"), exports);
144
144
  __exportStar(require("./xml_consistency"), exports);
145
+ __exportStar(require("./constant_classes"), exports);
145
146
  //# sourceMappingURL=index.js.map
@@ -61,6 +61,8 @@ class ObsoleteStatementConf extends _basic_rule_config_1.BasicRuleConfig {
61
61
  this.sortByFS = true;
62
62
  /** Checks for CALL TRANSFORMATION OBJECTS */
63
63
  this.callTransformation = true;
64
+ /** Check for POSIX REGEX usage */
65
+ this.regex = true;
64
66
  }
65
67
  }
66
68
  exports.ObsoleteStatementConf = ObsoleteStatementConf;
@@ -109,7 +111,9 @@ FREE MEMORY: https://help.sap.com/doc/abapdocu_752_index_htm/7.52/en-us/abapfree
109
111
 
110
112
  SORT BY FS: https://help.sap.com/doc/abapdocu_752_index_htm/7.52/en-US/abapsort_itab_obsolete.htm
111
113
 
112
- CALL TRANSFORMATION OBJECTS: https://help.sap.com/doc/abapdocu_752_index_htm/7.52/en-US/abapcall_transformation_objects.htm`,
114
+ CALL TRANSFORMATION OBJECTS: https://help.sap.com/doc/abapdocu_752_index_htm/7.52/en-US/abapcall_transformation_objects.htm
115
+
116
+ POSIX REGEX: https://help.sap.com/doc/abapdocu_755_index_htm/7.55/en-US/index.htm`,
113
117
  };
114
118
  }
115
119
  getConfig() {
@@ -266,6 +270,35 @@ CALL TRANSFORMATION OBJECTS: https://help.sap.com/doc/abapdocu_752_index_htm/7.5
266
270
  issues.push(issue);
267
271
  }
268
272
  }
273
+ if (configVersion >= version_1.Version.v756 && this.conf.regex) {
274
+ if (sta instanceof Statements.Find || sta instanceof Statements.Replace) {
275
+ const concat = staNode.concatTokens().toUpperCase();
276
+ if (concat.includes("REGEX")) {
277
+ const issue = issue_1.Issue.atStatement(file, staNode, "REGEX obsolete, use PCRE", this.getMetadata().key, this.conf.severity);
278
+ issues.push(issue);
279
+ }
280
+ }
281
+ else {
282
+ const classNameExpression = staNode.findAllExpressions(Expressions.ClassName);
283
+ const methodNameExpression = staNode.findAllExpressions(Expressions.MethodName);
284
+ if (classNameExpression.length !== 0 && methodNameExpression.length !== 0) {
285
+ const className = classNameExpression[0].concatTokens();
286
+ const methodName = methodNameExpression[0].concatTokens();
287
+ if (className === "cl_abap_regex") {
288
+ if (methodName === "create_posix") {
289
+ const issue = issue_1.Issue.atStatement(file, staNode, "create_posix obsolete, use create_pcre", this.getMetadata().key, this.conf.severity);
290
+ issues.push(issue);
291
+ }
292
+ }
293
+ else if (className === "cl_abap_matcher") {
294
+ if (methodName.includes("posix")) {
295
+ const issue = issue_1.Issue.atStatement(file, staNode, "posix methods obsolete, use pcre methods", this.getMetadata().key, this.conf.severity);
296
+ issues.push(issue);
297
+ }
298
+ }
299
+ }
300
+ }
301
+ }
269
302
  }
270
303
  return issues;
271
304
  }
@@ -45,7 +45,11 @@ ENDIF.`,
45
45
  if (obj.getType() === "INTF") {
46
46
  return [];
47
47
  }
48
- if (this.reg.getConfig().getVersion() < version_1.Version.v740sp02 && this.reg.getConfig().getVersion() !== version_1.Version.Cloud) {
48
+ const vers = this.reg.getConfig().getVersion();
49
+ if (vers === version_1.Version.OpenABAP) {
50
+ return [];
51
+ }
52
+ else if (vers < version_1.Version.v740sp02 && vers !== version_1.Version.Cloud) {
49
53
  return [];
50
54
  }
51
55
  const statements = file.getStatements();
@@ -15,6 +15,7 @@ var Version;
15
15
  Version["v753"] = "v753";
16
16
  Version["v754"] = "v754";
17
17
  Version["v755"] = "v755";
18
+ Version["v756"] = "v756";
18
19
  Version["Cloud"] = "Cloud";
19
20
  })(Version = exports.Version || (exports.Version = {}));
20
21
  exports.defaultVersion = Version.v755;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/core",
3
- "version": "2.78.12",
3
+ "version": "2.79.2",
4
4
  "description": "abaplint - Core API",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/abaplint.d.ts",
@@ -54,7 +54,7 @@
54
54
  },
55
55
  "homepage": "https://abaplint.org",
56
56
  "devDependencies": {
57
- "@microsoft/api-extractor": "^7.18.7",
57
+ "@microsoft/api-extractor": "^7.18.9",
58
58
  "@types/chai": "^4.2.21",
59
59
  "@types/mocha": "^9.0.0",
60
60
  "@types/node": "^16.9.1",