@abaplint/core 2.102.41 → 2.102.43

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.
@@ -2949,6 +2949,7 @@ export declare const enum IdentifierMeta {
2949
2949
  EventParameter = "event_parameter",
2950
2950
  FormParameter = "form_parameter",
2951
2951
  ReadOnly = "read_only",
2952
+ Abstract = "abstract",
2952
2953
  PassByValue = "pass_by_value",
2953
2954
  InlineDefinition = "inline",
2954
2955
  BuiltIn = "built-in",
@@ -3113,9 +3114,10 @@ declare interface IMethodDefinitions {
3113
3114
  }
3114
3115
 
3115
3116
  export declare interface IMethodLengthResult {
3117
+ className: string;
3116
3118
  name: string;
3117
3119
  count: number;
3118
- file: IFile;
3120
+ file: ABAPFile;
3119
3121
  pos: Position;
3120
3122
  }
3121
3123
 
@@ -4126,7 +4128,7 @@ declare class MethodParameters_2 implements IMethodParameters {
4126
4128
  private readonly exceptions;
4127
4129
  private readonly defaults;
4128
4130
  private readonly filename;
4129
- constructor(node: StatementNode, filename: string, scope: CurrentScope);
4131
+ constructor(node: StatementNode, filename: string, scope: CurrentScope, abstractMethod: boolean);
4130
4132
  getFilename(): string;
4131
4133
  getOptional(): string[];
4132
4134
  getAll(): TypedIdentifier[];
@@ -65,7 +65,7 @@ class MethodDefinition extends _identifier_1.Identifier {
65
65
  this.exceptions.push(name);
66
66
  }
67
67
  this.visibility = visibility;
68
- this.parameters = new method_parameters_1.MethodParameters(node, this.filename, scope);
68
+ this.parameters = new method_parameters_1.MethodParameters(node, this.filename, scope, this.abstract);
69
69
  }
70
70
  getVisibility() {
71
71
  return this.visibility;
@@ -16,7 +16,7 @@ const _scope_type_1 = require("../5_syntax/_scope_type");
16
16
  // this.exceptions = [];
17
17
  // also consider RAISING vs EXCEPTIONS
18
18
  class MethodParameters {
19
- constructor(node, filename, scope) {
19
+ constructor(node, filename, scope, abstractMethod) {
20
20
  if (!(node.get() instanceof method_def_1.MethodDef)) {
21
21
  throw new Error("MethodDefinition, expected MethodDef as part of input node");
22
22
  }
@@ -32,7 +32,7 @@ class MethodParameters {
32
32
  // need the scope for LIKE typing inside method parameters
33
33
  const parentName = scope.getName();
34
34
  scope.push(_scope_type_1.ScopeType.MethodDefinition, "method definition", node.getStart(), filename);
35
- this.parse(node, scope, filename, parentName);
35
+ this.parse(node, scope, filename, parentName, abstractMethod);
36
36
  scope.pop(node.getEnd());
37
37
  }
38
38
  getFilename() {
@@ -108,7 +108,7 @@ class MethodParameters {
108
108
  return this.defaults[parameter.toUpperCase()];
109
109
  }
110
110
  ///////////////////
111
- parse(node, scope, filename, parentName) {
111
+ parse(node, scope, filename, parentName, abstractMethod) {
112
112
  var _a, _b;
113
113
  const handler = node.findFirstExpression(Expressions.EventHandler);
114
114
  if (handler) {
@@ -148,7 +148,7 @@ class MethodParameters {
148
148
  }
149
149
  const importing = node.findFirstExpression(Expressions.MethodDefImporting);
150
150
  if (importing) {
151
- this.add(this.importing, importing, scope, ["importing" /* IdentifierMeta.MethodImporting */]);
151
+ this.add(this.importing, importing, scope, ["importing" /* IdentifierMeta.MethodImporting */], abstractMethod);
152
152
  if (importing.concatTokens().toUpperCase().includes(" PREFERRED PARAMETER")) {
153
153
  this.preferred = importing.getLastToken().getStr().toUpperCase();
154
154
  if (this.preferred.startsWith("!")) {
@@ -158,11 +158,11 @@ class MethodParameters {
158
158
  }
159
159
  const exporting = node.findFirstExpression(Expressions.MethodDefExporting);
160
160
  if (exporting) {
161
- this.add(this.exporting, exporting, scope, ["exporting" /* IdentifierMeta.MethodExporting */]);
161
+ this.add(this.exporting, exporting, scope, ["exporting" /* IdentifierMeta.MethodExporting */], abstractMethod);
162
162
  }
163
163
  const changing = node.findFirstExpression(Expressions.MethodDefChanging);
164
164
  if (changing) {
165
- this.add(this.changing, changing, scope, ["changing" /* IdentifierMeta.MethodChanging */]);
165
+ this.add(this.changing, changing, scope, ["changing" /* IdentifierMeta.MethodChanging */], abstractMethod);
166
166
  }
167
167
  const returning = node.findFirstExpression(Expressions.MethodDefReturning);
168
168
  if (returning) {
@@ -208,7 +208,7 @@ class MethodParameters {
208
208
  this.importing.push(...tempImporting);
209
209
  }
210
210
  }
211
- add(target, source, scope, meta) {
211
+ add(target, source, scope, meta, abstractMethod) {
212
212
  var _a;
213
213
  for (const opt of source.findAllExpressions(Expressions.MethodParamOptional)) {
214
214
  const p = opt.findDirectExpression(Expressions.MethodParam);
@@ -222,6 +222,9 @@ class MethodParameters {
222
222
  else if (meta.includes("importing" /* IdentifierMeta.MethodImporting */)) {
223
223
  extraMeta.push("read_only" /* IdentifierMeta.ReadOnly */);
224
224
  }
225
+ if (abstractMethod === true) {
226
+ extraMeta.push("abstract" /* IdentifierMeta.Abstract */);
227
+ }
225
228
  const id = new method_param_1.MethodParam().runSyntax(p, scope, this.filename, [...meta, ...extraMeta]);
226
229
  scope.addIdentifier(id);
227
230
  target.push(id);
@@ -65,7 +65,7 @@ class Registry {
65
65
  }
66
66
  static abaplintVersion() {
67
67
  // magic, see build script "version.sh"
68
- return "2.102.41";
68
+ return "2.102.43";
69
69
  }
70
70
  getDDICReferences() {
71
71
  return this.ddicReferences;
@@ -142,7 +142,8 @@ FIND statement with MATCH COUNT is considered okay if subrc is not checked`,
142
142
  if (statement.get() instanceof _statement_1.Comment) {
143
143
  continue;
144
144
  }
145
- else if (statement.get() instanceof Statements.EndIf) {
145
+ else if (statement.get() instanceof Statements.EndIf
146
+ || statement.get() instanceof Statements.EndTestSeam) {
146
147
  continue;
147
148
  }
148
149
  else {
@@ -169,7 +170,8 @@ FIND statement with MATCH COUNT is considered okay if subrc is not checked`,
169
170
  return true;
170
171
  }
171
172
  }
172
- else if (statement.get() instanceof Statements.EndIf) {
173
+ else if (statement.get() instanceof Statements.EndIf
174
+ || statement.get() instanceof Statements.EndTestSeam) {
173
175
  continue;
174
176
  }
175
177
  else {
@@ -34,7 +34,9 @@ class MethodLength {
34
34
  key: "method_length",
35
35
  title: "Method/Form Length",
36
36
  shortDescription: `Checks relating to method/form length.`,
37
- extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#keep-methods-small`,
37
+ extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#keep-methods-small
38
+
39
+ Abstract methods without statements are considered okay.`,
38
40
  tags: [_irule_1.RuleTag.Styleguide, _irule_1.RuleTag.SingleFile],
39
41
  };
40
42
  }
@@ -79,6 +81,9 @@ class MethodLength {
79
81
  continue;
80
82
  }
81
83
  if (s.count === 0 && this.conf.errorWhenEmpty === true) {
84
+ if (this.isAbstract(s)) {
85
+ continue;
86
+ }
82
87
  const issue = issue_1.Issue.atPosition(s.file, s.pos, this.getDescription(IssueType.EmptyMethod, "0", type), this.getMetadata().key, this.conf.severity);
83
88
  issues.push(issue);
84
89
  continue;
@@ -91,6 +96,10 @@ class MethodLength {
91
96
  }
92
97
  return issues;
93
98
  }
99
+ isAbstract(result) {
100
+ const cdef = result.file.getInfo().getClassDefinitionByName(result.className);
101
+ return (cdef === null || cdef === void 0 ? void 0 : cdef.isAbstract) === true;
102
+ }
94
103
  }
95
104
  exports.MethodLength = MethodLength;
96
105
  //# sourceMappingURL=method_length.js.map
@@ -19,6 +19,8 @@ class UnusedVariablesConf extends _basic_rule_config_1.BasicRuleConfig {
19
19
  * @uniqueItems true
20
20
  */
21
21
  this.skipNames = [];
22
+ /** skip parameters from abstract methods */
23
+ this.skipAbstract = false;
22
24
  }
23
25
  }
24
26
  exports.UnusedVariablesConf = UnusedVariablesConf;
@@ -161,6 +163,9 @@ Errors found in INCLUDES are reported for the main program.`,
161
163
  && this.conf.skipNames.some((a) => a.toUpperCase() === name)) {
162
164
  continue;
163
165
  }
166
+ else if (this.conf.skipAbstract === true && meta.includes("abstract" /* IdentifierMeta.Abstract */)) {
167
+ continue;
168
+ }
164
169
  else if (name === "ME"
165
170
  || name === "SUPER"
166
171
  || meta.includes("selection_screen_tab" /* IdentifierMeta.SelectionScreenTab */)
@@ -26,7 +26,7 @@ class FormLengthStats {
26
26
  }
27
27
  else if (type instanceof Statements.EndForm) {
28
28
  if (pos) {
29
- res.push({ name, count, file, pos });
29
+ res.push({ name: name, className: "", count, file, pos });
30
30
  }
31
31
  else {
32
32
  continue;
@@ -2,31 +2,37 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MethodLengthStats = void 0;
4
4
  const Statements = require("../abap/2_statements/statements");
5
+ const Expressions = require("../abap/2_statements/expressions");
5
6
  const expressions_1 = require("../abap/2_statements/expressions");
6
7
  const _abap_object_1 = require("../objects/_abap_object");
7
8
  const _statement_1 = require("../abap/2_statements/statements/_statement");
8
9
  class MethodLengthStats {
9
10
  static run(obj) {
11
+ var _a;
10
12
  const res = [];
11
13
  let pos = undefined;
12
- let name = "";
14
+ let methodName = "";
13
15
  let count = 0;
14
16
  let method = false;
15
17
  if (!(obj instanceof _abap_object_1.ABAPObject)) {
16
18
  return [];
17
19
  }
18
20
  for (const file of obj.getABAPFiles()) {
21
+ let className = "";
19
22
  for (const stat of file.getStatements()) {
20
23
  const type = stat.get();
21
24
  if (type instanceof Statements.MethodImplementation) {
22
25
  pos = stat.getFirstToken().getStart();
23
- name = this.findName(stat);
26
+ methodName = this.findName(stat);
24
27
  method = true;
25
28
  count = 0;
26
29
  }
30
+ else if (type instanceof Statements.ClassImplementation) {
31
+ className = ((_a = stat.findFirstExpression(Expressions.ClassName)) === null || _a === void 0 ? void 0 : _a.concatTokens()) || "INTERNAL_ERROR";
32
+ }
27
33
  else if (type instanceof Statements.EndMethod) {
28
34
  if (pos) {
29
- res.push({ name, count, file, pos });
35
+ res.push({ name: methodName, className, count, file, pos });
30
36
  }
31
37
  else {
32
38
  continue;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/core",
3
- "version": "2.102.41",
3
+ "version": "2.102.43",
4
4
  "description": "abaplint - Core API",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/abaplint.d.ts",
@@ -50,10 +50,10 @@
50
50
  },
51
51
  "homepage": "https://abaplint.org",
52
52
  "devDependencies": {
53
- "@microsoft/api-extractor": "^7.36.4",
53
+ "@microsoft/api-extractor": "^7.37.0",
54
54
  "@types/chai": "^4.3.6",
55
55
  "@types/mocha": "^10.0.1",
56
- "@types/node": "^20.6.0",
56
+ "@types/node": "^20.6.2",
57
57
  "chai": "^4.3.8",
58
58
  "eslint": "^8.49.0",
59
59
  "mocha": "^10.2.0",