@abaplint/core 2.119.67 → 2.120.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.
@@ -1491,7 +1491,7 @@ export declare class Config implements IConfiguration {
1491
1491
  getGlobal(): IGlobalConfig;
1492
1492
  getSyntaxSetttings(): ISyntaxSettings;
1493
1493
  getRelease(): ABAPRelease;
1494
- getOpenABAP(): boolean;
1494
+ isOpenABAP(): boolean;
1495
1495
  getVersion(): Version;
1496
1496
  getLanguageVersion(): LanguageVersion;
1497
1497
  private checkVersion;
@@ -3475,7 +3475,7 @@ export declare interface IConfiguration {
3475
3475
  getVersion(): Version;
3476
3476
  getRelease(): ABAPRelease;
3477
3477
  getLanguageVersion(): LanguageVersion;
3478
- getOpenABAP(): boolean;
3478
+ isOpenABAP(): boolean;
3479
3479
  getSyntaxSetttings(): ISyntaxSettings;
3480
3480
  readByRule(rule: string): any;
3481
3481
  readByKey(rule: string, key: string): any;
@@ -45,7 +45,7 @@ class CurrentScope {
45
45
  return this.reg.getConfig().getLanguageVersion();
46
46
  }
47
47
  getOpenABAP() {
48
- return this.reg.getConfig().getOpenABAP();
48
+ return this.reg.getConfig().isOpenABAP();
49
49
  }
50
50
  getRegistry() {
51
51
  return this.reg;
@@ -0,0 +1,59 @@
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.checkOffsetLength = checkOffsetLength;
37
+ const Expressions = __importStar(require("../../2_statements/expressions"));
38
+ const basic_1 = require("../../types/basic");
39
+ const _syntax_input_1 = require("../_syntax_input");
40
+ const _builtin_1 = require("../_builtin");
41
+ // Offsets or lengths cannot be specified for STRING or XSTRING fields
42
+ // passed as a method parameter source. Returns true if an issue was reported.
43
+ function checkOffsetLength(source, sourceType, method, input) {
44
+ const chain = source.findDirectExpression(Expressions.FieldChain);
45
+ const isCalculated = source.findDirectExpression(Expressions.Source) !== undefined;
46
+ const hasOffsetOrLength = chain !== undefined
47
+ && isCalculated === false
48
+ && (chain.findDirectExpression(Expressions.FieldOffset) !== undefined
49
+ || chain.findDirectExpression(Expressions.FieldLength) !== undefined);
50
+ if (hasOffsetOrLength
51
+ && !(method instanceof _builtin_1.BuiltInMethod)
52
+ && (sourceType instanceof basic_1.StringType || sourceType instanceof basic_1.XStringType)) {
53
+ const message = `Offsets or lengths cannot be specified for fields of type "STRING" or "XSTRING" in the current statement`;
54
+ input.issues.push((0, _syntax_input_1.syntaxIssue)(input, source.getFirstToken(), message));
55
+ return true;
56
+ }
57
+ return false;
58
+ }
59
+ //# sourceMappingURL=_check_offset_length.js.map
@@ -43,7 +43,7 @@ const source_1 = require("./source");
43
43
  const _type_utils_1 = require("../_type_utils");
44
44
  const _syntax_input_1 = require("../_syntax_input");
45
45
  const constant_1 = require("./constant");
46
- const _builtin_1 = require("../_builtin");
46
+ const _check_offset_length_1 = require("./_check_offset_length");
47
47
  class MethodCallParam {
48
48
  static runSyntax(node, input, method) {
49
49
  if (!(node.get() instanceof Expressions.MethodCallParam)) {
@@ -104,17 +104,7 @@ class MethodCallParam {
104
104
  let sourceType = undefined;
105
105
  if (child.get() instanceof Expressions.Source) {
106
106
  sourceType = source_1.Source.runSyntax(child, input, targetType);
107
- const chain = child.findDirectExpression(Expressions.FieldChain);
108
- const isCalculated = child.findDirectExpression(Expressions.Source) !== undefined;
109
- const hasOffsetOrLength = chain !== undefined
110
- && isCalculated === false
111
- && (chain.findDirectExpression(Expressions.FieldOffset) !== undefined
112
- || chain.findDirectExpression(Expressions.FieldLength) !== undefined);
113
- if (hasOffsetOrLength
114
- && !(method instanceof _builtin_1.BuiltInMethod)
115
- && (sourceType instanceof basic_1.StringType || sourceType instanceof basic_1.XStringType)) {
116
- const message = `Offsets or lengths cannot be specified for fields of type "STRING" or "XSTRING" in the current statement`;
117
- input.issues.push((0, _syntax_input_1.syntaxIssue)(input, child.getFirstToken(), message));
107
+ if ((0, _check_offset_length_1.checkOffsetLength)(child, sourceType, method, input)) {
118
108
  return;
119
109
  }
120
110
  }
@@ -45,6 +45,7 @@ const _syntax_input_1 = require("../_syntax_input");
45
45
  const assert_error_1 = require("../assert_error");
46
46
  const field_chain_1 = require("./field_chain");
47
47
  const _reference_1 = require("../_reference");
48
+ const _check_offset_length_1 = require("./_check_offset_length");
48
49
  class MethodParameters {
49
50
  constructor() {
50
51
  this.requiredParameters = undefined;
@@ -215,7 +216,6 @@ class MethodParameters {
215
216
  }
216
217
  }
217
218
  parameterListS(node, input, method) {
218
- var _a;
219
219
  if (node === undefined) {
220
220
  return [];
221
221
  }
@@ -223,14 +223,21 @@ class MethodParameters {
223
223
  throw new assert_error_1.AssertError("parameterListS, unexpected node");
224
224
  }
225
225
  const ret = [];
226
+ const supplied = new Set();
226
227
  for (const c of node.getChildren()) {
227
228
  if (!(c.get() instanceof Expressions.ParameterS) || !(c instanceof nodes_1.ExpressionNode)) {
228
229
  throw new assert_error_1.AssertError("parameterListS, unexpected node, child");
229
230
  }
230
- const name = (_a = c.findDirectExpression(Expressions.ParameterName)) === null || _a === void 0 ? void 0 : _a.getFirstToken().getStr().toUpperCase();
231
- if (name === undefined) {
231
+ const nameNode = c.findDirectExpression(Expressions.ParameterName);
232
+ const name = nameNode === null || nameNode === void 0 ? void 0 : nameNode.getFirstToken().getStr().toUpperCase();
233
+ if (name === undefined || nameNode === undefined) {
232
234
  throw new assert_error_1.AssertError("parameterListS, no name determined");
233
235
  }
236
+ if (supplied.has(name)) {
237
+ const message = `Method parameter "${name}" is supplied more than once`;
238
+ input.issues.push((0, _syntax_input_1.syntaxIssue)(input, nameNode.getFirstToken(), message));
239
+ }
240
+ supplied.add(name);
234
241
  const source = c.findDirectExpression(Expressions.Source);
235
242
  if (source === undefined) {
236
243
  throw new assert_error_1.AssertError("parameterListS, no source found");
@@ -248,6 +255,7 @@ class MethodParameters {
248
255
  targetType = method;
249
256
  }
250
257
  let sourceType = source_1.Source.runSyntax(source, input, targetType);
258
+ (0, _check_offset_length_1.checkOffsetLength)(source, sourceType, method, input);
251
259
  if (sourceType === undefined) {
252
260
  if (method instanceof basic_1.VoidType) {
253
261
  sourceType = method;
@@ -263,7 +271,6 @@ class MethodParameters {
263
271
  return ret;
264
272
  }
265
273
  parameterListT(node, input) {
266
- var _a;
267
274
  if (node === undefined) {
268
275
  return [];
269
276
  }
@@ -271,14 +278,21 @@ class MethodParameters {
271
278
  throw new assert_error_1.AssertError("parameterListT, unexpected node");
272
279
  }
273
280
  const ret = [];
281
+ const supplied = new Set();
274
282
  for (const c of node.getChildren()) {
275
283
  if (!(c.get() instanceof Expressions.ParameterT) || !(c instanceof nodes_1.ExpressionNode)) {
276
284
  throw new assert_error_1.AssertError("parameterListT, unexpected node, child");
277
285
  }
278
- const name = (_a = c.findDirectExpression(Expressions.ParameterName)) === null || _a === void 0 ? void 0 : _a.getFirstToken().getStr().toUpperCase();
279
- if (name === undefined) {
286
+ const nameNode = c.findDirectExpression(Expressions.ParameterName);
287
+ const name = nameNode === null || nameNode === void 0 ? void 0 : nameNode.getFirstToken().getStr().toUpperCase();
288
+ if (name === undefined || nameNode === undefined) {
280
289
  throw new assert_error_1.AssertError("parameterListT, no name determined");
281
290
  }
291
+ if (supplied.has(name)) {
292
+ const message = `Method parameter "${name}" is supplied more than once`;
293
+ input.issues.push((0, _syntax_input_1.syntaxIssue)(input, nameNode.getFirstToken(), message));
294
+ }
295
+ supplied.add(name);
282
296
  const target = c.findDirectExpression(Expressions.Target);
283
297
  if (target === undefined) {
284
298
  throw new assert_error_1.AssertError("parameterListT, no target found");
@@ -41,6 +41,7 @@ const basic_1 = require("../../types/basic");
41
41
  const target_1 = require("../expressions/target");
42
42
  const _reference_1 = require("../_reference");
43
43
  const _syntax_input_1 = require("../_syntax_input");
44
+ const _type_utils_1 = require("../_type_utils");
44
45
  class Catch {
45
46
  runSyntax(node, input) {
46
47
  var _a, _b;
@@ -91,7 +92,22 @@ class Catch {
91
92
  }
92
93
  }
93
94
  else if (target) {
94
- target_1.Target.runSyntax(target, input);
95
+ const targetType = target_1.Target.runSyntax(target, input);
96
+ if (targetType instanceof basic_1.ObjectReferenceType) {
97
+ for (const c of node.findDirectExpressions(Expressions.ClassName)) {
98
+ const token = c.getFirstToken();
99
+ const className = token.getStr().toUpperCase();
100
+ const found = input.scope.existsObject(className);
101
+ if (found === null || found === void 0 ? void 0 : found.id) {
102
+ const catchType = new basic_1.ObjectReferenceType(found.id);
103
+ if (new _type_utils_1.TypeUtils(input.scope).isAssignableStrict(catchType, targetType) === false) {
104
+ const message = "CATCH target not compatible with " + className;
105
+ input.issues.push((0, _syntax_input_1.syntaxIssue)(input, token, message));
106
+ return;
107
+ }
108
+ }
109
+ }
110
+ }
95
111
  }
96
112
  }
97
113
  }
@@ -8,7 +8,7 @@ class CDSDefineAbstract extends combi_1.Expression {
8
8
  getRunnable() {
9
9
  const field = (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.optPrio)((0, combi_1.str)("KEY")), cds_name_1.CDSName, ":", _1.CDSType, ";");
10
10
  const compsiOrAssoci = (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), cds_name_1.CDSName, ":", (0, combi_1.alt)(_1.CDSComposition, _1.CDSAssociation), ";");
11
- return (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), "DEFINE", (0, combi_1.opt)("ROOT"), "ABSTRACT", "ENTITY", cds_name_1.CDSName, (0, combi_1.opt)(_1.CDSWithParameters), (0, combi_1.str)("{"), (0, combi_1.plus)((0, combi_1.alt)(field, compsiOrAssoci)), (0, combi_1.str)("}"), (0, combi_1.opt)(";"));
11
+ return (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.opt)("DEFINE"), (0, combi_1.opt)("ROOT"), "ABSTRACT", "ENTITY", cds_name_1.CDSName, (0, combi_1.opt)(_1.CDSWithParameters), (0, combi_1.str)("{"), (0, combi_1.plus)((0, combi_1.alt)(field, compsiOrAssoci)), (0, combi_1.str)("}"), (0, combi_1.opt)(";"));
12
12
  }
13
13
  }
14
14
  exports.CDSDefineAbstract = CDSDefineAbstract;
@@ -9,7 +9,7 @@ class CDSDefineCustom extends combi_1.Expression {
9
9
  getRunnable() {
10
10
  const field = (0, combi_1.seq)((0, combi_1.optPrio)((0, combi_1.str)("KEY")), cds_name_1.CDSName, ":", cds_type_1.CDSType, ";");
11
11
  const compsiOrAssoci = (0, combi_1.seq)(cds_name_1.CDSName, ":", (0, combi_1.alt)(_1.CDSComposition, _1.CDSAssociation), ";");
12
- return (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.str)("DEFINE"), (0, combi_1.opt)((0, combi_1.str)("ROOT")), (0, combi_1.str)("CUSTOM ENTITY"), cds_name_1.CDSName, (0, combi_1.opt)(_1.CDSWithParameters), (0, combi_1.str)("{"), (0, combi_1.plus)((0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.alt)(field, compsiOrAssoci))), (0, combi_1.str)("}"), (0, combi_1.opt)(";"));
12
+ return (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.opt)("DEFINE"), (0, combi_1.opt)("ROOT"), (0, combi_1.str)("CUSTOM ENTITY"), cds_name_1.CDSName, (0, combi_1.opt)(_1.CDSWithParameters), (0, combi_1.str)("{"), (0, combi_1.plus)((0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.alt)(field, compsiOrAssoci))), (0, combi_1.str)("}"), (0, combi_1.opt)(";"));
13
13
  }
14
14
  }
15
15
  exports.CDSDefineCustom = CDSDefineCustom;
@@ -13,7 +13,7 @@ class CDSDefineExternalEntity extends combi_1.Expression {
13
13
  const body = (0, combi_1.plus)((0, combi_1.alt)(field, assocOrComp));
14
14
  const externalEntity = (0, combi_1.seq)((0, combi_1.opt)("WRITABLE"), "EXTERNAL", "ENTITY", _1.CDSName, (0, combi_1.opt)(externalName), (0, combi_1.opt)(_1.CDSWithParameters));
15
15
  const staticEntity = (0, combi_1.seq)("STATIC", "ENTITY", _1.CDSName, (0, combi_1.opt)(externalName));
16
- return (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), "DEFINE", (0, combi_1.alt)(externalEntity, staticEntity), (0, combi_1.str)("{"), body, (0, combi_1.str)("}"), (0, combi_1.opt)((0, combi_1.seq)("WITH", "FEDERATED", "DATA", (0, combi_1.optPrio)((0, combi_1.alt)((0, combi_1.seq)("PROVIDED", "AT", "RUNTIME"), (0, combi_1.seq)("PROVIDED", "BY", _1.CDSName))))), (0, combi_1.opt)(";"));
16
+ return (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.opt)("DEFINE"), (0, combi_1.alt)(externalEntity, staticEntity), (0, combi_1.str)("{"), body, (0, combi_1.str)("}"), (0, combi_1.opt)((0, combi_1.seq)("WITH", "FEDERATED", "DATA", (0, combi_1.optPrio)((0, combi_1.alt)((0, combi_1.seq)("PROVIDED", "AT", "RUNTIME"), (0, combi_1.seq)("PROVIDED", "BY", _1.CDSName))))), (0, combi_1.opt)(";"));
17
17
  }
18
18
  }
19
19
  exports.CDSDefineExternalEntity = CDSDefineExternalEntity;
@@ -15,7 +15,7 @@ class CDSDefineHierarchy extends combi_1.Expression {
15
15
  const depthValue = (0, combi_1.altPrio)(_1.CDSString, _1.CDSInteger, _1.CDSPrefixedName);
16
16
  const loadMode = (0, combi_1.altPrio)("BULK", "INCREMENTAL", _1.CDSPrefixedName);
17
17
  const hierarchyBody = (0, combi_1.seq)("SOURCE", _1.CDSName, (0, combi_1.opt)(_1.CDSParametersSelect), "CHILD", "TO", "PARENT", "ASSOCIATION", _1.CDSName, (0, combi_1.opt)(directory), (0, combi_1.opt)(datePeriod), (0, combi_1.opt)((0, combi_1.seq)("START", "WHERE", _1.CDSCondition)), (0, combi_1.opt)(siblingsOrder), (0, combi_1.opt)((0, combi_1.seq)("LOAD", loadMode)), (0, combi_1.opt)((0, combi_1.seq)("DEPTH", depthValue)), (0, combi_1.opt)((0, combi_1.seq)("NODETYPE", _1.CDSName)), (0, combi_1.opt)((0, combi_1.seq)("MULTIPLE", "PARENTS", (0, combi_1.altPrio)("NOT ALLOWED", "ALLOWED", (0, combi_1.seq)("LEAVES", (0, combi_1.optPrio)("ONLY"))))), (0, combi_1.opt)((0, combi_1.seq)("ORPHANS", (0, combi_1.altPrio)("IGNORE", "ROOT", "ERROR"))), (0, combi_1.opt)((0, combi_1.seq)("CYCLES", (0, combi_1.altPrio)("BREAKUP", "ERROR"))), (0, combi_1.opt)((0, combi_1.seq)("GENERATE", "SPANTREE")), (0, combi_1.opt)((0, combi_1.seq)("CACHE", (0, combi_1.altPrio)("ON", "OFF", "FORCE"))));
18
- return (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), "DEFINE", "HIERARCHY", _1.CDSName, (0, combi_1.opt)(_1.CDSWithParameters), "AS", "PARENT", "CHILD", "HIERARCHY", "(", hierarchyBody, ")", "{", (0, combi_1.seq)(field, (0, combi_1.star)((0, combi_1.seq)(",", field))), "}", (0, combi_1.opt)(";"));
18
+ return (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.opt)("DEFINE"), "HIERARCHY", _1.CDSName, (0, combi_1.opt)(_1.CDSWithParameters), "AS", "PARENT", "CHILD", "HIERARCHY", "(", hierarchyBody, ")", "{", (0, combi_1.seq)(field, (0, combi_1.star)((0, combi_1.seq)(",", field))), "}", (0, combi_1.opt)(";"));
19
19
  }
20
20
  }
21
21
  exports.CDSDefineHierarchy = CDSDefineHierarchy;
@@ -8,7 +8,7 @@ class CDSDefineProjection extends combi_1.Expression {
8
8
  getRunnable() {
9
9
  // redefine association _Assoc redirected to [composition child | parent] Entity
10
10
  const redefineAssoc = (0, combi_1.seq)("REDEFINE", "ASSOCIATION", _1.CDSName, "REDIRECTED", "TO", (0, combi_1.optPrio)((0, combi_1.altPrio)((0, combi_1.seq)("COMPOSITION", "CHILD"), "PARENT")), _1.CDSName);
11
- return (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), "DEFINE", (0, combi_1.opt)("ROOT"), (0, combi_1.opt)("TRANSIENT"), "VIEW", (0, combi_1.ver)(__1.Release.v755, (0, combi_1.opt)("ENTITY")), _1.CDSName, (0, combi_1.opt)(_1.CDSProviderContract), (0, combi_1.opt)(_1.CDSWithParameters), "AS PROJECTION ON", _1.CDSName, (0, combi_1.opt)(_1.CDSParametersSelect), (0, combi_1.opt)(_1.CDSAs), (0, combi_1.star)((0, combi_1.altPrio)(_1.CDSAssociation, redefineAssoc)), (0, combi_1.str)("{"), (0, combi_1.seq)(_1.CDSElement, (0, combi_1.star)((0, combi_1.seq)(",", _1.CDSElement)), (0, combi_1.opt)(",")), (0, combi_1.str)("}"), (0, combi_1.opt)(_1.CDSWhere), (0, combi_1.opt)(";"));
11
+ return (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.opt)("DEFINE"), (0, combi_1.opt)("ROOT"), (0, combi_1.opt)("TRANSIENT"), "VIEW", (0, combi_1.ver)(__1.Release.v755, (0, combi_1.opt)("ENTITY")), _1.CDSName, (0, combi_1.opt)(_1.CDSProviderContract), (0, combi_1.opt)(_1.CDSWithParameters), "AS PROJECTION ON", _1.CDSName, (0, combi_1.opt)(_1.CDSParametersSelect), (0, combi_1.opt)(_1.CDSAs), (0, combi_1.star)((0, combi_1.altPrio)(_1.CDSAssociation, redefineAssoc)), (0, combi_1.str)("{"), (0, combi_1.seq)(_1.CDSElement, (0, combi_1.star)((0, combi_1.seq)(",", _1.CDSElement)), (0, combi_1.opt)(",")), (0, combi_1.str)("}"), (0, combi_1.opt)(_1.CDSWhere), (0, combi_1.opt)(";"));
12
12
  }
13
13
  }
14
14
  exports.CDSDefineProjection = CDSDefineProjection;
@@ -12,7 +12,7 @@ class CDSDefineTableEntity extends combi_1.Expression {
12
12
  const elementList = (0, combi_1.seq)(_1.CDSElement, (0, combi_1.star)((0, combi_1.seq)(",", _1.CDSElement)), (0, combi_1.opt)(","));
13
13
  const elements = (0, combi_1.seq)((0, combi_1.str)("{"), (0, combi_1.altPrio)("*", elementList), (0, combi_1.str)("}"));
14
14
  const selectBody = (0, combi_1.seq)("AS", "SELECT", "FROM", _1.CDSSource, (0, combi_1.star)(_1.CDSJoin), (0, combi_1.star)((0, combi_1.altPrio)(_1.CDSComposition, _1.CDSAssociation)), (0, combi_1.opt)(elements), (0, combi_1.optPrio)(_1.CDSWhere));
15
- return (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), "DEFINE", (0, combi_1.opt)("ROOT"), "TABLE", "ENTITY", _1.CDSName, (0, combi_1.opt)(_1.CDSWithParameters), (0, combi_1.altPrio)((0, combi_1.seq)((0, combi_1.str)("{"), inlineBody, (0, combi_1.str)("}")), selectBody), (0, combi_1.opt)(";"));
15
+ return (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.opt)("DEFINE"), (0, combi_1.opt)("ROOT"), "TABLE", "ENTITY", _1.CDSName, (0, combi_1.opt)(_1.CDSWithParameters), (0, combi_1.altPrio)((0, combi_1.seq)((0, combi_1.str)("{"), inlineBody, (0, combi_1.str)("}")), selectBody), (0, combi_1.opt)(";"));
16
16
  }
17
17
  }
18
18
  exports.CDSDefineTableEntity = CDSDefineTableEntity;
@@ -181,7 +181,7 @@ class Config {
181
181
  }
182
182
  return (0, version_1.versionToABAPRelease)(v);
183
183
  }
184
- getOpenABAP() {
184
+ isOpenABAP() {
185
185
  return this.getRelease() === version_1.Release["open-abap"];
186
186
  }
187
187
  getVersion() {
@@ -75,7 +75,7 @@ class Registry {
75
75
  }
76
76
  static abaplintVersion() {
77
77
  // magic, see build script "version.js"
78
- return "2.119.67";
78
+ return "2.120.1";
79
79
  }
80
80
  getDDICReferences() {
81
81
  return this.ddicReferences;
@@ -0,0 +1,254 @@
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.ClearExportingParameters = exports.ClearExportingParametersConf = void 0;
37
+ const issue_1 = require("../issue");
38
+ const _basic_rule_config_1 = require("./_basic_rule_config");
39
+ const _irule_1 = require("./_irule");
40
+ const syntax_1 = require("../abap/5_syntax/syntax");
41
+ const _abap_object_1 = require("../objects/_abap_object");
42
+ const _scope_type_1 = require("../abap/5_syntax/_scope_type");
43
+ const objects_1 = require("../objects");
44
+ const _reference_1 = require("../abap/5_syntax/_reference");
45
+ const basic_1 = require("../abap/types/basic");
46
+ const _statement_1 = require("../abap/2_statements/statements/_statement");
47
+ const edit_helper_1 = require("../edit_helper");
48
+ const Expressions = __importStar(require("../abap/2_statements/expressions"));
49
+ class ClearExportingParametersConf extends _basic_rule_config_1.BasicRuleConfig {
50
+ constructor() {
51
+ super(...arguments);
52
+ /** Skip specific parameter names, case insensitive
53
+ * @uniqueItems true
54
+ */
55
+ this.skipNames = [];
56
+ }
57
+ }
58
+ exports.ClearExportingParametersConf = ClearExportingParametersConf;
59
+ class ClearExportingParameters {
60
+ constructor() {
61
+ this.conf = new ClearExportingParametersConf();
62
+ }
63
+ getMetadata() {
64
+ return {
65
+ key: "clear_exporting_parameters",
66
+ title: "Clear EXPORTING parameters",
67
+ shortDescription: `Checks that EXPORTING parameters passed by reference are cleared or assigned before they are read`,
68
+ extendedInformation: `An EXPORTING parameter passed by reference behaves like a CHANGING parameter: it is not
69
+ initialized when the method is called, so it can still contain a value supplied by the caller. Clear or overwrite it
70
+ before reading it, so a leftover value is not accidentally used.
71
+
72
+ https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#clear-or-overwrite-exporting-reference-parameters
73
+
74
+ https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/abenref_transf_output_param_guidl.htm
75
+
76
+ Note: EXPORTING parameters passed by VALUE are always initialized and are therefore not reported.
77
+ Reading and writing the parameter in the same statement (e.g. "ev_result = ev_result + 1") is reported,
78
+ as the source is evaluated before the parameter is assigned.
79
+ Objects containing parser or syntax errors are not reported.
80
+
81
+ Only class and interface method implementations are checked, function module parameters are currently not supported.`,
82
+ tags: [_irule_1.RuleTag.Styleguide],
83
+ badExample: `CLASS lcl DEFINITION.
84
+ PUBLIC SECTION.
85
+ METHODS foo EXPORTING ev_result TYPE i.
86
+ ENDCLASS.
87
+ CLASS lcl IMPLEMENTATION.
88
+ METHOD foo.
89
+ ev_result = ev_result + 1.
90
+ ENDMETHOD.
91
+ ENDCLASS.`,
92
+ goodExample: `CLASS lcl DEFINITION.
93
+ PUBLIC SECTION.
94
+ METHODS foo EXPORTING ev_result TYPE i.
95
+ ENDCLASS.
96
+ CLASS lcl IMPLEMENTATION.
97
+ METHOD foo.
98
+ CLEAR ev_result.
99
+ ev_result = ev_result + 1.
100
+ ENDMETHOD.
101
+ ENDCLASS.`,
102
+ };
103
+ }
104
+ getConfig() {
105
+ return this.conf;
106
+ }
107
+ setConfig(conf) {
108
+ this.conf = conf;
109
+ if (this.conf.skipNames === undefined) {
110
+ this.conf.skipNames = [];
111
+ }
112
+ }
113
+ initialize(reg) {
114
+ this.reg = reg;
115
+ return this;
116
+ }
117
+ run(obj) {
118
+ if (!(obj instanceof _abap_object_1.ABAPObject) || obj instanceof objects_1.Interface) {
119
+ return [];
120
+ }
121
+ for (const file of obj.getABAPFiles()) {
122
+ for (const statement of file.getStatements()) {
123
+ if (statement.get() instanceof _statement_1.Unknown) {
124
+ return []; // contains parser errors
125
+ }
126
+ }
127
+ }
128
+ const syntax = new syntax_1.SyntaxLogic(this.reg, obj).run();
129
+ if (syntax.issues.length > 0) {
130
+ return []; // contains syntax errors
131
+ }
132
+ const issues = [];
133
+ this.traverse(syntax.spaghetti.getTop(), obj, issues);
134
+ return issues;
135
+ }
136
+ traverse(node, obj, issues) {
137
+ if (node.getIdentifier().stype === _scope_type_1.ScopeType.Method) {
138
+ this.checkMethod(node, obj, issues);
139
+ }
140
+ for (const child of node.getChildren()) {
141
+ this.traverse(child, obj, issues);
142
+ }
143
+ }
144
+ checkMethod(node, obj, issues) {
145
+ const parameters = this.findExportingByReference(node, obj);
146
+ if (parameters.length === 0) {
147
+ return;
148
+ }
149
+ const references = this.collectReferences(node);
150
+ for (const parameter of parameters) {
151
+ const issue = this.checkParameter(parameter, references, obj);
152
+ if (issue !== undefined) {
153
+ issues.push(issue);
154
+ }
155
+ }
156
+ }
157
+ findExportingByReference(node, obj) {
158
+ var _a;
159
+ const ret = [];
160
+ const vars = node.getData().vars;
161
+ for (const name in vars) {
162
+ const parameter = vars[name];
163
+ const meta = parameter.getMeta();
164
+ if (meta.includes("exporting" /* IdentifierMeta.MethodExporting */) === false
165
+ || meta.includes("pass_by_value" /* IdentifierMeta.PassByValue */) === true) {
166
+ continue;
167
+ }
168
+ else if ((_a = this.conf.skipNames) === null || _a === void 0 ? void 0 : _a.some(s => s.toUpperCase() === name.toUpperCase())) {
169
+ continue;
170
+ }
171
+ const type = parameter.getType();
172
+ if (type instanceof basic_1.VoidType || type instanceof basic_1.UnknownType) {
173
+ continue; // e.g. RAP magic parameters, or unresolved types
174
+ }
175
+ else if (this.isPassByValue(parameter, obj) === true) {
176
+ continue; // VALUE(..) parameters are always initialized
177
+ }
178
+ ret.push(parameter);
179
+ }
180
+ return ret;
181
+ }
182
+ isPassByValue(parameter, obj) {
183
+ var _a;
184
+ // the PassByValue meta is not set for EXPORTING parameters, so determine it from the definition
185
+ const file = obj.getABAPFileByName(parameter.getFilename());
186
+ if (file === undefined) {
187
+ return false;
188
+ }
189
+ const statement = edit_helper_1.EditHelper.findStatement(parameter.getToken(), file);
190
+ if (statement === undefined) {
191
+ return false;
192
+ }
193
+ for (const param of statement.findAllExpressions(Expressions.MethodParam)) {
194
+ const nameToken = (_a = param.findFirstExpression(Expressions.MethodParamName)) === null || _a === void 0 ? void 0 : _a.getFirstToken();
195
+ if (nameToken !== undefined && nameToken.getStart().equals(parameter.getStart())) {
196
+ return param.getFirstToken().getStr().toUpperCase() === "VALUE";
197
+ }
198
+ }
199
+ return false;
200
+ }
201
+ collectReferences(node) {
202
+ // methods do not nest, so all descendant scopes (FOR, LET, ...) belong to this method
203
+ const ret = [...node.getData().references];
204
+ for (const child of node.getChildren()) {
205
+ ret.push(...this.collectReferences(child));
206
+ }
207
+ return ret;
208
+ }
209
+ checkParameter(parameter, references, obj) {
210
+ let firstRead = undefined;
211
+ let earliestWrite = undefined;
212
+ for (const reference of references) {
213
+ if (reference.resolved === undefined || parameter.equals(reference.resolved) === false) {
214
+ continue;
215
+ }
216
+ const pos = reference.position.getStart();
217
+ if (reference.referenceType === _reference_1.ReferenceType.DataReadReference) {
218
+ if (firstRead === undefined || pos.isBefore(firstRead.position.getStart())) {
219
+ firstRead = reference;
220
+ }
221
+ }
222
+ else if (reference.referenceType === _reference_1.ReferenceType.DataWriteReference) {
223
+ if (earliestWrite === undefined || pos.isBefore(earliestWrite)) {
224
+ earliestWrite = pos;
225
+ }
226
+ }
227
+ }
228
+ if (firstRead === undefined) {
229
+ return undefined; // never read, no hazard
230
+ }
231
+ // the parameter is safe only if it is written in a statement strictly before the first read
232
+ const readStatement = this.statementStart(firstRead.position.getStart(), obj);
233
+ const writeStatement = earliestWrite === undefined ? undefined : this.statementStart(earliestWrite, obj);
234
+ if (writeStatement !== undefined && readStatement !== undefined && writeStatement.isBefore(readStatement)) {
235
+ return undefined;
236
+ }
237
+ const message = `EXPORTING parameter "${parameter.getName().toLowerCase()}" read before it is cleared or assigned`;
238
+ return issue_1.Issue.atIdentifier(firstRead.position, message, this.getMetadata().key, this.conf.severity);
239
+ }
240
+ statementStart(pos, obj) {
241
+ for (const file of obj.getABAPFiles()) {
242
+ for (const statement of file.getStatements()) {
243
+ const start = statement.getStart();
244
+ const end = statement.getEnd();
245
+ if (pos.equals(start) || (pos.isAfter(start) && pos.isBefore(end))) {
246
+ return start;
247
+ }
248
+ }
249
+ }
250
+ return undefined;
251
+ }
252
+ }
253
+ exports.ClearExportingParameters = ClearExportingParameters;
254
+ //# sourceMappingURL=clear_exporting_parameters.js.map
@@ -204,7 +204,7 @@ Make sure to test the downported code, it might not always be completely correct
204
204
  initialize(reg) {
205
205
  this.lowReg = reg;
206
206
  const config = this.lowReg.getConfig();
207
- if (config.getRelease() === version_1.Release.v702 || config.getOpenABAP()) {
207
+ if (config.getRelease() === version_1.Release.v702 || config.isOpenABAP()) {
208
208
  this.initHighReg();
209
209
  }
210
210
  return this;
@@ -237,7 +237,7 @@ Make sure to test the downported code, it might not always be completely correct
237
237
  const ret = [];
238
238
  this.counter = 1;
239
239
  const config = this.lowReg.getConfig();
240
- if (config.getRelease() !== version_1.Release.v702 && !config.getOpenABAP()) {
240
+ if (config.getRelease() !== version_1.Release.v702 && !config.isOpenABAP()) {
241
241
  return ret;
242
242
  }
243
243
  else if (!(lowObj instanceof _abap_object_1.ABAPObject)) {
@@ -1109,7 +1109,7 @@ ${indentation}`);
1109
1109
  outlineCatchSimple(node, lowFile) {
1110
1110
  // outlines "CATCH cx_bcs INTO DATA(lx_bcs_excep).", note that this does not need to look at types
1111
1111
  var _a, _b;
1112
- if (this.lowReg.getConfig().getOpenABAP()) {
1112
+ if (this.lowReg.getConfig().isOpenABAP()) {
1113
1113
  return undefined;
1114
1114
  }
1115
1115
  if (!(node.get() instanceof Statements.Catch)) {
@@ -1158,7 +1158,7 @@ ${indentation}CATCH ${className} INTO ${targetName}.`;
1158
1158
  if (!(node.get() instanceof Statements.Move)) {
1159
1159
  return undefined;
1160
1160
  }
1161
- if (this.lowReg.getConfig().getOpenABAP()) {
1161
+ if (this.lowReg.getConfig().isOpenABAP()) {
1162
1162
  return undefined;
1163
1163
  }
1164
1164
  const target = node.findFirstExpression(Expressions.Target);
@@ -1214,7 +1214,7 @@ ${indentation}CATCH ${className} INTO ${targetName}.`;
1214
1214
  return issue_1.Issue.atToken(lowFile, node.getFirstToken(), "Outline DATA", this.getMetadata().key, this.conf.severity, fix);
1215
1215
  }
1216
1216
  partiallyImplemented(node, lowFile) {
1217
- if (this.lowReg.getConfig().getOpenABAP()) {
1217
+ if (this.lowReg.getConfig().isOpenABAP()) {
1218
1218
  return undefined;
1219
1219
  }
1220
1220
  if (node.get() instanceof Statements.InterfaceDef) {
@@ -1890,7 +1890,7 @@ ${indentation} output = ${uniqueName}.\n`;
1890
1890
  if (!(node.get() instanceof Statements.Loop)) {
1891
1891
  return undefined;
1892
1892
  }
1893
- if (this.lowReg.getConfig().getOpenABAP()) {
1893
+ if (this.lowReg.getConfig().isOpenABAP()) {
1894
1894
  return undefined;
1895
1895
  }
1896
1896
  const source = (_a = node.findDirectExpression(Expressions.LoopSource)) === null || _a === void 0 ? void 0 : _a.findDirectExpression(Expressions.SimpleSource2);
@@ -2566,7 +2566,7 @@ ${indentation} output = ${uniqueName}.\n`;
2566
2566
  outlineData(node, lowFile, highSyntax) {
2567
2567
  // hmm, no guard here, as DATA(SDF) is valid in 702
2568
2568
  var _a, _b;
2569
- if (this.lowReg.getConfig().getOpenABAP()) {
2569
+ if (this.lowReg.getConfig().isOpenABAP()) {
2570
2570
  return undefined;
2571
2571
  }
2572
2572
  for (const i of node.findAllExpressionsRecursive(Expressions.InlineData)) {
@@ -2785,7 +2785,7 @@ ${indentation} output = ${uniqueName}.\n`;
2785
2785
  return false;
2786
2786
  }
2787
2787
  replaceXsdBool(node, lowFile, highSyntax) {
2788
- if (this.lowReg.getConfig().getOpenABAP()) {
2788
+ if (this.lowReg.getConfig().isOpenABAP()) {
2789
2789
  return undefined;
2790
2790
  }
2791
2791
  const spag = highSyntax.spaghetti.lookupPosition(node.getFirstToken().getStart(), lowFile.getFilename());
@@ -2914,7 +2914,7 @@ ${indentation} output = ${uniqueName}.\n`;
2914
2914
  }
2915
2915
  replaceLineFunctions(node, lowFile, highSyntax, highFile) {
2916
2916
  var _a, _b;
2917
- if (this.lowReg.getConfig().getOpenABAP()) {
2917
+ if (this.lowReg.getConfig().isOpenABAP()) {
2918
2918
  return undefined;
2919
2919
  }
2920
2920
  const spag = highSyntax.spaghetti.lookupPosition(node.getFirstToken().getStart(), lowFile.getFilename());
@@ -45,6 +45,7 @@ __exportStar(require("./check_subrc"), exports);
45
45
  __exportStar(require("./check_syntax"), exports);
46
46
  __exportStar(require("./check_text_elements"), exports);
47
47
  __exportStar(require("./check_transformation_exists"), exports);
48
+ __exportStar(require("./clear_exporting_parameters"), exports);
48
49
  __exportStar(require("./class_attribute_names"), exports);
49
50
  __exportStar(require("./classic_exceptions_overlap"), exports);
50
51
  __exportStar(require("./cloud_types"), exports);
@@ -150,6 +151,7 @@ __exportStar(require("./preferred_compare_operator"), exports);
150
151
  __exportStar(require("./prefix_is_current_class"), exports);
151
152
  __exportStar(require("./reduce_procedural_code"), exports);
152
153
  __exportStar(require("./reduce_string_templates"), exports);
154
+ __exportStar(require("./redundant_conversion"), exports);
153
155
  __exportStar(require("./release_idoc"), exports);
154
156
  __exportStar(require("./remove_descriptions"), exports);
155
157
  __exportStar(require("./rfc_error_handling"), exports);
@@ -32,7 +32,7 @@ class InlineDataOldVersions extends _abap_rule_1.ABAPRule {
32
32
  runParsed(file) {
33
33
  const issues = [];
34
34
  if ((0, version_1.releaseAtLeast)(this.reg.getConfig().getRelease(), version_1.Release.v740sp02)
35
- || this.reg.getConfig().getOpenABAP()
35
+ || this.reg.getConfig().isOpenABAP()
36
36
  || this.reg.getConfig().getLanguageVersion() === version_1.LanguageVersion.Cloud) {
37
37
  return [];
38
38
  }
@@ -80,7 +80,7 @@ Not considered optional branches:
80
80
  const release = this.reg.getConfig().getRelease();
81
81
  if (release === version_1.Release.v700
82
82
  || release === version_1.Release.v702
83
- || this.reg.getConfig().getOpenABAP()) {
83
+ || this.reg.getConfig().isOpenABAP()) {
84
84
  return [];
85
85
  }
86
86
  const struc = file.getStructure();
@@ -0,0 +1,253 @@
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.RedundantConversion = exports.RedundantConversionConf = void 0;
37
+ const Expressions = __importStar(require("../abap/2_statements/expressions"));
38
+ const Statements = __importStar(require("../abap/2_statements/statements"));
39
+ const _reference_1 = require("../abap/5_syntax/_reference");
40
+ const constant_1 = require("../abap/5_syntax/expressions/constant");
41
+ const syntax_1 = require("../abap/5_syntax/syntax");
42
+ const nodes_1 = require("../abap/nodes");
43
+ const _typed_identifier_1 = require("../abap/types/_typed_identifier");
44
+ const basic_1 = require("../abap/types/basic");
45
+ const issue_1 = require("../issue");
46
+ const _abap_object_1 = require("../objects/_abap_object");
47
+ const _basic_rule_config_1 = require("./_basic_rule_config");
48
+ const _irule_1 = require("./_irule");
49
+ const edit_helper_1 = require("../edit_helper");
50
+ const version_1 = require("../version");
51
+ class RedundantConversionConf extends _basic_rule_config_1.BasicRuleConfig {
52
+ }
53
+ exports.RedundantConversionConf = RedundantConversionConf;
54
+ class RedundantConversion {
55
+ constructor() {
56
+ this.conf = new RedundantConversionConf();
57
+ }
58
+ getMetadata() {
59
+ return {
60
+ key: "redundant_conversion",
61
+ title: "Redundant Conversion",
62
+ shortDescription: `Find redundant CONV expressions`,
63
+ extendedInformation: `Reports CONV expressions whose operand already has the conversion's target type.`,
64
+ tags: [_irule_1.RuleTag.Quickfix],
65
+ badExample: `DATA text TYPE string.
66
+ text = CONV string( text ).`,
67
+ goodExample: `DATA text TYPE string.
68
+ text = text.`,
69
+ };
70
+ }
71
+ getConfig() {
72
+ return this.conf;
73
+ }
74
+ setConfig(conf) {
75
+ this.conf = conf;
76
+ }
77
+ initialize(reg) {
78
+ this.reg = reg;
79
+ return this;
80
+ }
81
+ run(obj) {
82
+ var _a, _b;
83
+ if (!(0, version_1.releaseAtLeast)(this.reg.getConfig().getRelease(), version_1.Release.v740sp02)
84
+ && !this.reg.getConfig().isOpenABAP()) {
85
+ return [];
86
+ }
87
+ if (!(obj instanceof _abap_object_1.ABAPObject)) {
88
+ return [];
89
+ }
90
+ const syntax = new syntax_1.SyntaxLogic(this.reg, obj).run();
91
+ if (syntax.issues.length > 0) {
92
+ return [];
93
+ }
94
+ const issues = [];
95
+ for (const file of obj.getABAPFiles()) {
96
+ const structure = file.getStructure();
97
+ if (structure === undefined) {
98
+ continue;
99
+ }
100
+ for (const source of structure.findAllExpressions(Expressions.Source)) {
101
+ if (source.getFirstToken().getStr().toUpperCase() !== "CONV") {
102
+ continue;
103
+ }
104
+ const typeExpression = source.findDirectExpression(Expressions.TypeNameOrInfer);
105
+ const bodySource = (_a = source.findDirectExpression(Expressions.ConvBody)) === null || _a === void 0 ? void 0 : _a.findDirectExpression(Expressions.Source);
106
+ if (typeExpression === undefined
107
+ || bodySource === undefined) {
108
+ continue;
109
+ }
110
+ const scope = syntax.spaghetti.lookupPosition(source.getFirstToken().getStart(), file.getFilename());
111
+ if (scope === undefined) {
112
+ continue;
113
+ }
114
+ const target = (_b = scope.getData().references.find(reference => reference.referenceType === _reference_1.ReferenceType.InferredType
115
+ && reference.position.getStart().equals(typeExpression.getFirstToken().getStart()))) === null || _b === void 0 ? void 0 : _b.resolved;
116
+ const operandType = this.sourceType(bodySource, scope);
117
+ if (!(target instanceof _typed_identifier_1.TypedIdentifier)) {
118
+ continue;
119
+ }
120
+ const operandHasSameType = operandType !== undefined && this.sameType(target.getType(), operandType);
121
+ const arithmeticHasSameContext = this.arithmeticUsesSameTargetType(source, bodySource, file, scope, target.getType());
122
+ if (operandHasSameType === false && arithmeticHasSameContext === false) {
123
+ continue;
124
+ }
125
+ const closingParen = source.getDirectTokens().find(token => token.getStr() === ")" && token.getStart().isAfter(bodySource.getLastToken().getStart()));
126
+ if (closingParen === undefined) {
127
+ continue;
128
+ }
129
+ const preserveParentheses = bodySource.findDirectExpression(Expressions.ArithOperator) !== undefined
130
+ || bodySource.findDirectTokenByText("&&") !== undefined;
131
+ // Apply the later edit first so the original positions remain valid when
132
+ // both parts of the CONV wrapper are changed on the same line.
133
+ const fix = edit_helper_1.EditHelper.merge(edit_helper_1.EditHelper.replaceRange(file, bodySource.getLastToken().getEnd(), closingParen.getEnd(), preserveParentheses ? ")" : ""), edit_helper_1.EditHelper.replaceRange(file, source.getFirstToken().getStart(), bodySource.getFirstToken().getStart(), preserveParentheses ? "(" : ""));
134
+ issues.push(issue_1.Issue.atRange(file, source.getFirstToken().getStart(), closingParen.getEnd(), "Redundant CONV expression", this.getMetadata().key, this.conf.severity, fix));
135
+ }
136
+ }
137
+ return issues;
138
+ }
139
+ arithmeticUsesSameTargetType(conversion, bodySource, file, scope, conversionType) {
140
+ var _a, _b;
141
+ if (bodySource.findDirectExpression(Expressions.ArithOperator) === undefined) {
142
+ return false;
143
+ }
144
+ const statement = file.getStatements().find(candidate => candidate.includesToken(conversion.getFirstToken()));
145
+ if (!((statement === null || statement === void 0 ? void 0 : statement.get()) instanceof Statements.Move)) {
146
+ return false;
147
+ }
148
+ const targetToken = (_a = statement.findDirectExpression(Expressions.Target)) === null || _a === void 0 ? void 0 : _a.getFirstToken();
149
+ if (targetToken === undefined) {
150
+ return false;
151
+ }
152
+ const assignmentTarget = (_b = scope.getData().references.find(reference => reference.referenceType === _reference_1.ReferenceType.DataWriteReference
153
+ && reference.position.getStart().equals(targetToken.getStart()))) === null || _b === void 0 ? void 0 : _b.resolved;
154
+ return assignmentTarget instanceof _typed_identifier_1.TypedIdentifier
155
+ && this.sameType(conversionType, assignmentTarget.getType());
156
+ }
157
+ sourceType(source, scope) {
158
+ let context;
159
+ for (const child of source.getChildren()) {
160
+ if (!(child instanceof nodes_1.ExpressionNode)) {
161
+ continue;
162
+ }
163
+ else if (child.get() instanceof Expressions.FieldChain) {
164
+ context = this.fieldChainType(child, scope);
165
+ if (context === undefined) {
166
+ return undefined;
167
+ }
168
+ }
169
+ else if (child.get() instanceof Expressions.Constant) {
170
+ context = this.infer(context, constant_1.Constant.runSyntax(child));
171
+ }
172
+ else if (child.get() instanceof Expressions.Source) {
173
+ context = this.infer(context, this.sourceType(child, scope));
174
+ }
175
+ else if (child.get() instanceof Expressions.ArithOperator) {
176
+ if (child.concatTokens() === "**") {
177
+ context = new basic_1.FloatType();
178
+ }
179
+ }
180
+ else {
181
+ return undefined;
182
+ }
183
+ }
184
+ if (source.findDirectTokenByText("&&")) {
185
+ return basic_1.StringType.get();
186
+ }
187
+ return context;
188
+ }
189
+ fieldChainType(fieldChain, scope) {
190
+ var _a;
191
+ const operand = (_a = scope.getData().references.find(reference => reference.referenceType === _reference_1.ReferenceType.DataReadReference
192
+ && reference.position.getStart().equals(fieldChain.getFirstToken().getStart()))) === null || _a === void 0 ? void 0 : _a.resolved;
193
+ if (!(operand instanceof _typed_identifier_1.TypedIdentifier)) {
194
+ return undefined;
195
+ }
196
+ let type = operand.getType();
197
+ for (const child of fieldChain.getChildren()) {
198
+ if (!(child instanceof nodes_1.ExpressionNode)
199
+ || child.get() instanceof Expressions.SourceField) {
200
+ continue;
201
+ }
202
+ else if (child.get() instanceof Expressions.ComponentName) {
203
+ if (type instanceof basic_1.TableType) {
204
+ type = type.getRowType();
205
+ }
206
+ if (!(type instanceof basic_1.StructureType)) {
207
+ return undefined;
208
+ }
209
+ type = type.getComponentByName(child.concatTokens());
210
+ }
211
+ else {
212
+ // Offsets, table expressions, attributes, and dereferences need more
213
+ // context than the initial data reference provides.
214
+ return undefined;
215
+ }
216
+ }
217
+ return type;
218
+ }
219
+ infer(context, found) {
220
+ if (context instanceof basic_1.FloatType && found instanceof basic_1.IntegerType) {
221
+ return context;
222
+ }
223
+ else if (context instanceof basic_1.IntegerType && found instanceof basic_1.HexType) {
224
+ return context;
225
+ }
226
+ else if ((context instanceof basic_1.IntegerType || context instanceof basic_1.FloatType) && (found === null || found === void 0 ? void 0 : found.isGeneric())) {
227
+ return context;
228
+ }
229
+ return found;
230
+ }
231
+ sameType(first, second) {
232
+ var _a, _b;
233
+ if (first instanceof basic_1.UnknownType
234
+ || second instanceof basic_1.UnknownType
235
+ || first instanceof basic_1.VoidType
236
+ || second instanceof basic_1.VoidType
237
+ || first.isGeneric()
238
+ || second.isGeneric()) {
239
+ return false;
240
+ }
241
+ if (first.constructor !== second.constructor) {
242
+ return false;
243
+ }
244
+ if (first instanceof basic_1.StructureType || first instanceof basic_1.TableType) {
245
+ const firstName = (_a = first.getQualifiedName()) === null || _a === void 0 ? void 0 : _a.toUpperCase();
246
+ const secondName = (_b = second.getQualifiedName()) === null || _b === void 0 ? void 0 : _b.toUpperCase();
247
+ return firstName !== undefined && firstName === secondName;
248
+ }
249
+ return first.toABAP() === second.toABAP();
250
+ }
251
+ }
252
+ exports.RedundantConversion = RedundantConversion;
253
+ //# sourceMappingURL=redundant_conversion.js.map
@@ -75,7 +75,7 @@ class SQLEscapeHostVariables extends _abap_rule_1.ABAPRule {
75
75
  }
76
76
  if (!(0, version_1.releaseAtLeast)(this.reg.getConfig().getRelease(), version_1.Release.v740sp02)
77
77
  && this.reg.getConfig().getLanguageVersion() !== version_1.LanguageVersion.Cloud
78
- && !this.reg.getConfig().getOpenABAP()) {
78
+ && !this.reg.getConfig().isOpenABAP()) {
79
79
  return [];
80
80
  }
81
81
  for (const s of file.getStatements()) {
@@ -80,7 +80,7 @@ ENDIF.`,
80
80
  }
81
81
  const release = this.reg.getConfig().getRelease();
82
82
  const langVers = this.reg.getConfig().getLanguageVersion();
83
- if (this.reg.getConfig().getOpenABAP()) {
83
+ if (this.reg.getConfig().isOpenABAP()) {
84
84
  return [];
85
85
  }
86
86
  else if (!(0, version_1.releaseAtLeast)(release, version_1.Release.v740sp02) && langVers !== version_1.LanguageVersion.Cloud) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/core",
3
- "version": "2.119.67",
3
+ "version": "2.120.1",
4
4
  "description": "abaplint - Core API",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/abaplint.d.ts",