@abaplint/core 2.120.42 → 2.120.44

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.
@@ -558,12 +558,22 @@ declare namespace BasicTypes {
558
558
  export { BasicTypes }
559
559
 
560
560
  declare class BehaviorDefinition extends AbstractObject {
561
+ private parsedData;
561
562
  getType(): string;
562
563
  getAllowedNaming(): {
563
564
  maxLength: number;
564
565
  allowNamespace: boolean;
565
566
  };
566
567
  getDescription(): string | undefined;
568
+ setDirty(): void;
569
+ findSourceFile(): IFile | undefined;
570
+ listEntities(): readonly {
571
+ name: string;
572
+ alias: string | undefined;
573
+ }[];
574
+ /** finds the entity name for a given alias, undefined if the alias is not defined */
575
+ findEntityNameByAlias(alias: string): string | undefined;
576
+ private parseSource;
567
577
  }
568
578
 
569
579
  declare class BehaviorDefinitionName extends Expression {
@@ -1626,6 +1636,8 @@ export declare class CurrentScope {
1626
1636
  addSQLConversion(fieldName: string, message: string, token: Token): void;
1627
1637
  findFunctionModule(name: string | undefined): FunctionModuleDefinition | undefined;
1628
1638
  findObjectDefinition(name: string | undefined): IClassDefinition | IInterfaceDefinition | undefined;
1639
+ /** the BDEF from "FOR BEHAVIOR OF" of the enclosing global class, undefined if not a behavior pool */
1640
+ findBehaviorDefinition(): BehaviorDefinition | undefined;
1629
1641
  isBadiDef(name: string): boolean;
1630
1642
  existsObject(name: string | undefined): {
1631
1643
  id: Identifier | undefined;
@@ -3888,6 +3900,8 @@ declare interface InfoClassDefinition extends InfoInterfaceDefinition {
3888
3900
  duration: Duration | undefined;
3889
3901
  riskLevel: RiskLevel | undefined;
3890
3902
  isSharedMemory: boolean;
3903
+ /** name of the BDEF from "FOR BEHAVIOR OF", undefined if not a behavior pool */
3904
+ behaviorDefinitionName: string | undefined;
3891
3905
  }
3892
3906
 
3893
3907
  declare interface InfoClassImplementation {
@@ -4599,6 +4613,11 @@ declare class LockObject extends AbstractObject {
4599
4613
  getAllowedNaming(): IAllowedNaming;
4600
4614
  setDirty(): void;
4601
4615
  getPrimaryTable(): string | undefined;
4616
+ getParameters(): {
4617
+ VIEWFIELD: string;
4618
+ TABNAME?: string;
4619
+ FIELDNAME?: string;
4620
+ }[] | undefined;
4602
4621
  parseType(reg: IRegistry): AbstractType;
4603
4622
  parse(): {
4604
4623
  updated: boolean;
@@ -5324,6 +5343,7 @@ declare namespace Objects {
5324
5343
  AuthorizationObjectExtension,
5325
5344
  AuthorizationObject,
5326
5345
  BADIDefinition,
5346
+ ParsedBehaviorDefinition,
5327
5347
  BehaviorDefinition,
5328
5348
  BRFPlusSystemApplication,
5329
5349
  BSPApplication,
@@ -5624,13 +5644,23 @@ declare class ParenRightW extends Token {
5624
5644
  static railroad(): string;
5625
5645
  }
5626
5646
 
5647
+ declare type ParsedBehaviorDefinition = {
5648
+ /** entities defined in the behavior definition, alias is undefined if not specified */
5649
+ entities: {
5650
+ name: string;
5651
+ alias: string | undefined;
5652
+ }[];
5653
+ };
5654
+
5627
5655
  declare type ParsedDataDefinition = {
5628
5656
  sqlViewName: string | undefined;
5629
5657
  definitionName: string | undefined;
5630
5658
  description: string | undefined;
5659
+ /** name is the name of the element, nameInSource the name in the prefixed source, if aliased via "as" */
5631
5660
  fields: {
5632
5661
  key: boolean;
5633
5662
  name: string;
5663
+ nameInSource?: string;
5634
5664
  prefix: string;
5635
5665
  annotations: string[];
5636
5666
  }[];
@@ -13,7 +13,7 @@ class Write {
13
13
  const to = (0, combi_1.seq)("TO", expressions_1.Target);
14
14
  const options = (0, combi_1.per)(mask, to, (0, combi_1.seq)("EXPONENT", expressions_1.Source), "NO-GROUPING", "NO-ZERO", "CENTERED", (0, combi_1.seq)("INPUT", (0, combi_1.opt)(onOff)), "NO-GAP", "LEFT-JUSTIFIED", as, (0, combi_1.seq)("FRAMES", onOff), (0, combi_1.seq)("HOTSPOT", (0, combi_1.opt)(onOff)), "RIGHT-JUSTIFIED", (0, combi_1.seq)("TIME ZONE", expressions_1.Source), (0, combi_1.seq)("UNDER", expressions_1.Source), (0, combi_1.seq)("STYLE", expressions_1.Source), (0, combi_1.seq)("ROUND", expressions_1.Source), (0, combi_1.seq)("QUICKINFO", expressions_1.Source), "ENVIRONMENT TIME FORMAT", dateFormat, (0, combi_1.seq)("UNIT", expressions_1.Source), (0, combi_1.seq)("INTENSIFIED", (0, combi_1.opt)(onOff)), (0, combi_1.seq)("INDEX", expressions_1.Source), (0, combi_1.seq)("DECIMALS", expressions_1.Source), (0, combi_1.seq)("INVERSE", (0, combi_1.opt)(onOff)), expressions_1.Color, (0, combi_1.seq)("CURRENCY", expressions_1.Source), "RESET", "NO-SIGN");
15
15
  // Need to refactor all this sometime,
16
- const ret = (0, combi_1.seq)("WRITE", (0, combi_1.alt)((0, combi_1.seq)("AT /", (0, combi_1.opt)(expressions_1.Source), (0, combi_1.opt)("NO-GAP")), (0, combi_1.seq)((0, combi_1.opt)(expressions_1.WriteOffsetLength), (0, combi_1.alt)(expressions_1.Source, expressions_1.Dynamic, "/"), (0, combi_1.opt)(options))));
16
+ const ret = (0, combi_1.seq)("WRITE", (0, combi_1.alt)((0, combi_1.seq)("AT /", (0, combi_1.opt)(expressions_1.Source), (0, combi_1.opt)(options)), (0, combi_1.seq)((0, combi_1.opt)(expressions_1.WriteOffsetLength), (0, combi_1.alt)(expressions_1.Source, expressions_1.Dynamic, "/"), (0, combi_1.opt)(options))));
17
17
  return (0, combi_1.verNotLang)(version_1.LanguageVersion.Cloud, ret);
18
18
  }
19
19
  }
@@ -37,6 +37,7 @@ exports.ABAPFileInformationParser = void 0;
37
37
  const Structures = __importStar(require("../3_structures/structures"));
38
38
  const Expressions = __importStar(require("../2_statements/expressions"));
39
39
  const Statements = __importStar(require("../2_statements/statements"));
40
+ const nodes_1 = require("../nodes");
40
41
  const _identifier_1 = require("./_identifier");
41
42
  const Tokens = __importStar(require("../1_lexer/tokens"));
42
43
  const visibility_1 = require("./visibility");
@@ -176,6 +177,7 @@ class ABAPFileInformationParser {
176
177
  riskLevel,
177
178
  isAbstract: (cdef === null || cdef === void 0 ? void 0 : cdef.findDirectTokenByText("ABSTRACT")) !== undefined,
178
179
  isSharedMemory: concat.includes(" SHARED MEMORY ENABLED"),
180
+ behaviorDefinitionName: this.findBehaviorDefinitionName(cdef),
179
181
  isFinal: found.findFirstExpression(Expressions.ClassFinal) !== undefined,
180
182
  aliases,
181
183
  attributes,
@@ -185,6 +187,20 @@ class ABAPFileInformationParser {
185
187
  return classes;
186
188
  }
187
189
  ///////////////////
190
+ /** "FOR BEHAVIOR OF" and "FOR EVENTS OF" both use the BehaviorDefinitionName expression,
191
+ * so look at the token two positions before the expression to tell them apart */
192
+ findBehaviorDefinitionName(cdef) {
193
+ const children = (cdef === null || cdef === void 0 ? void 0 : cdef.getChildren()) || [];
194
+ for (let i = 2; i < children.length; i++) {
195
+ const child = children[i];
196
+ if (child instanceof nodes_1.ExpressionNode
197
+ && child.get() instanceof Expressions.BehaviorDefinitionName
198
+ && children[i - 2].concatTokens().toUpperCase() === "BEHAVIOR") {
199
+ return child.concatTokens();
200
+ }
201
+ }
202
+ return undefined;
203
+ }
188
204
  getImplementing(input) {
189
205
  const ret = [];
190
206
  for (const node of input.findAllStatements(Statements.InterfaceDef)) {
@@ -232,6 +232,18 @@ class CurrentScope {
232
232
  }
233
233
  return undefined;
234
234
  }
235
+ /** the BDEF from "FOR BEHAVIOR OF" of the enclosing global class, undefined if not a behavior pool */
236
+ findBehaviorDefinition() {
237
+ var _a;
238
+ if (this.parentObj.getType() !== "CLAS") {
239
+ return undefined;
240
+ }
241
+ const name = (_a = this.parentObj.getClassDefinition()) === null || _a === void 0 ? void 0 : _a.behaviorDefinitionName;
242
+ if (name === undefined) {
243
+ return undefined;
244
+ }
245
+ return this.reg.getObject("BDEF", name);
246
+ }
235
247
  isBadiDef(name) {
236
248
  const upper = name.toUpperCase();
237
249
  for (const enhs of this.reg.getObjectsByType("ENHS")) {
@@ -345,7 +345,7 @@ class BasicTypes {
345
345
  return undefined;
346
346
  }
347
347
  parseTable(node, name) {
348
- var _a, _b, _c, _d;
348
+ var _a, _b, _c;
349
349
  const typename = node.findFirstExpression(Expressions.TypeName) || node.findFirstExpression(Expressions.EntityAssociation);
350
350
  const text = (_a = node.findFirstExpression(Expressions.TypeTable)) === null || _a === void 0 ? void 0 : _a.concatTokens().toUpperCase();
351
351
  if (text === undefined) {
@@ -482,25 +482,31 @@ class BasicTypes {
482
482
  return new Types.TableType(structure, options);
483
483
  }
484
484
  else if (typename && this.isRAPTableFor(text)) {
485
- const name = typename.concatTokens();
486
- const ddlsName = this.getRAPBaseEntityName(name);
487
- const type = (_d = this.input.scope.getDDIC().lookupDDLS(ddlsName)) === null || _d === void 0 ? void 0 : _d.type;
488
- if (type) {
489
- return new Types.TableType(basic_1.VoidType.get("RAP-TODO"), options);
490
- }
491
- else if (this.isRAPDerivedEntityName(name)) {
492
- return Types.VoidType.get(name);
493
- }
494
- else if (this.input.scope.getDDIC().inErrorNamespace(ddlsName)) {
495
- return new Types.UnknownType(`DDLS ${ddlsName} not found`);
496
- }
497
- else {
498
- return Types.VoidType.get(name);
499
- }
485
+ return this.rapTableFor(typename.concatTokens(), options);
500
486
  }
501
487
  // fallback to old style syntax, OCCURS etc
502
488
  return this.parseType(node, name);
503
489
  }
490
+ /** type of a RAP derived table type, ie the "TABLE FOR LOCK zentity" part of a type */
491
+ rapTableFor(entityName, options) {
492
+ var _a;
493
+ const ddlsName = this.resolveRAPAlias(this.getRAPBaseEntityName(entityName));
494
+ if ((_a = this.input.scope.getDDIC().lookupDDLS(ddlsName)) === null || _a === void 0 ? void 0 : _a.type) {
495
+ return new Types.TableType(basic_1.VoidType.get("RAP-TODO"), options !== null && options !== void 0 ? options : {
496
+ withHeader: false,
497
+ keyType: Types.TableKeyType.user,
498
+ primaryKey: { name: "primary_key", type: basic_1.TableAccessType.standard, isUnique: false, keyFields: [] },
499
+ secondary: [],
500
+ });
501
+ }
502
+ else if (this.isRAPDerivedEntityName(entityName)) {
503
+ return Types.VoidType.get(entityName);
504
+ }
505
+ else if (this.input.scope.getDDIC().inErrorNamespace(ddlsName)) {
506
+ return new Types.UnknownType(`DDLS ${ddlsName} not found`);
507
+ }
508
+ return Types.VoidType.get(entityName);
509
+ }
504
510
  parseType(node, qualifiedName) {
505
511
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
506
512
  const typeName = node.findFirstExpression(Expressions.TypeName);
@@ -694,6 +700,12 @@ class BasicTypes {
694
700
  const splitAt = Math.min(...candidates);
695
701
  return name.substring(0, splitAt);
696
702
  }
703
+ /** inside a behavior pool the entities are referenced via the aliases defined in the BDEF */
704
+ resolveRAPAlias(name) {
705
+ var _a;
706
+ var _b;
707
+ return (_b = (_a = this.input.scope.findBehaviorDefinition()) === null || _a === void 0 ? void 0 : _a.findEntityNameByAlias(name)) !== null && _b !== void 0 ? _b : name;
708
+ }
697
709
  isRAPDerivedEntityName(name) {
698
710
  return name.includes("\\") || name.includes("~");
699
711
  }
@@ -41,6 +41,7 @@ const _typed_identifier_1 = require("./_typed_identifier");
41
41
  const basic_1 = require("./basic");
42
42
  const method_def_returning_1 = require("../5_syntax/expressions/method_def_returning");
43
43
  const method_param_1 = require("../5_syntax/expressions/method_param");
44
+ const basic_types_1 = require("../5_syntax/basic_types");
44
45
  const _object_oriented_1 = require("../5_syntax/_object_oriented");
45
46
  const _reference_1 = require("../5_syntax/_reference");
46
47
  const identifier_1 = require("../1_lexer/tokens/identifier");
@@ -228,24 +229,37 @@ class MethodParameters {
228
229
  }
229
230
  }
230
231
  workaroundRAP(node, input, parentName) {
232
+ var _a;
231
233
  const resultName = node.findExpressionAfterToken("RESULT");
232
234
  const concat = node.concatTokens().toUpperCase();
233
235
  const isRap = node.findExpressionAfterToken("IMPORTING")
234
236
  || (concat.includes(" IMPORTING REQUEST ") ? node.findExpressionAfterToken("REQUEST") : undefined);
235
237
  if (isRap) {
238
+ // "FOR LOCK" handlers have a well defined signature, so the types can be derived
239
+ const lockEntity = concat.includes(" FOR LOCK ")
240
+ ? (_a = node.findExpressionAfterToken("LOCK")) === null || _a === void 0 ? void 0 : _a.concatTokens()
241
+ : undefined;
236
242
  for (const foo of node.findDirectExpressions(Expressions.MethodParamName)) {
237
243
  if (foo === resultName) {
238
244
  continue;
239
245
  }
240
- this.importing.push(new _typed_identifier_1.TypedIdentifier(foo.getFirstToken(), input.filename, basic_1.VoidType.get("RapMethodParameter"), ["importing" /* IdentifierMeta.MethodImporting */]));
246
+ const type = lockEntity === undefined
247
+ ? basic_1.VoidType.get("RapMethodParameter")
248
+ : new basic_types_1.BasicTypes(input).rapTableFor(lockEntity);
249
+ this.importing.push(new _typed_identifier_1.TypedIdentifier(foo.getFirstToken(), input.filename, type, ["importing" /* IdentifierMeta.MethodImporting */]));
250
+ }
251
+ if (lockEntity !== undefined) {
252
+ // note: "mapped" is not part of the signature for "FOR LOCK"
253
+ const token = isRap.getFirstToken();
254
+ this.exporting.push(new _typed_identifier_1.TypedIdentifier(new identifier_1.Identifier(token.getStart(), "failed"), input.filename, basic_1.VoidType.get(`RESPONSE FOR FAILED EARLY ${lockEntity}`), ["exporting" /* IdentifierMeta.MethodExporting */]));
255
+ this.exporting.push(new _typed_identifier_1.TypedIdentifier(new identifier_1.Identifier(token.getStart(), "reported"), input.filename, basic_1.VoidType.get(`RESPONSE FOR REPORTED EARLY ${lockEntity}`), ["exporting" /* IdentifierMeta.MethodExporting */]));
241
256
  }
242
- if (concat.includes(" FOR VALIDATE ")
257
+ else if (concat.includes(" FOR VALIDATE ")
243
258
  || concat.includes(" FOR BEHAVIOR ")
244
259
  || concat.includes(" FOR DETERMINE ")
245
260
  || concat.includes(" FOR FEATURES ")
246
261
  || concat.includes(" FOR INSTANCE FEATURES ")
247
262
  || concat.includes(" FOR GLOBAL AUTHORIZATION ")
248
- || concat.includes(" FOR LOCK ")
249
263
  || concat.includes(" FOR PRECHECK ")
250
264
  || concat.includes(" FOR NUMBERING ")
251
265
  || concat.includes(" FOR READ ")
@@ -5,6 +5,7 @@ const basic_1 = require("../abap/types/basic");
5
5
  const ddic_1 = require("../ddic");
6
6
  class CDSDetermineTypes {
7
7
  parseType(reg, parsedData, ddlsName) {
8
+ var _a;
8
9
  const ddic = new ddic_1.DDIC(reg);
9
10
  if ((parsedData === null || parsedData === void 0 ? void 0 : parsedData.fields.length) === 0) {
10
11
  return basic_1.VoidType.get("DDLS:todo");
@@ -41,10 +42,11 @@ class CDSDetermineTypes {
41
42
  });
42
43
  continue;
43
44
  }
45
+ const nameInSource = (_a = f.nameInSource) !== null && _a !== void 0 ? _a : f.name;
44
46
  const lookup = ddic.lookupTableOrView(source.name);
45
47
  if (lookup.type) {
46
48
  if (lookup.type instanceof basic_1.StructureType) {
47
- const type = lookup.type.getComponentByName(f.name);
49
+ const type = lookup.type.getComponentByName(nameInSource);
48
50
  if (type) {
49
51
  components.push({
50
52
  name: f.name,
@@ -54,7 +56,7 @@ class CDSDetermineTypes {
54
56
  else {
55
57
  components.push({
56
58
  name: f.name,
57
- type: new basic_1.UnknownType(f.name + " not found in " + source.name + ", CDSDetermineTypes"),
59
+ type: new basic_1.UnknownType(nameInSource + " not found in " + source.name + ", CDSDetermineTypes"),
58
60
  });
59
61
  }
60
62
  }
@@ -3,6 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.BehaviorDefinition = void 0;
4
4
  const _abstract_object_1 = require("./_abstract_object");
5
5
  class BehaviorDefinition extends _abstract_object_1.AbstractObject {
6
+ constructor() {
7
+ super(...arguments);
8
+ this.parsedData = undefined;
9
+ }
6
10
  getType() {
7
11
  return "BDEF";
8
12
  }
@@ -16,6 +20,49 @@ class BehaviorDefinition extends _abstract_object_1.AbstractObject {
16
20
  // todo
17
21
  return undefined;
18
22
  }
23
+ setDirty() {
24
+ this.parsedData = undefined;
25
+ super.setDirty();
26
+ }
27
+ findSourceFile() {
28
+ return this.getFiles().find(f => f.getFilename().endsWith(".asbdef"));
29
+ }
30
+ listEntities() {
31
+ return this.parseSource().entities;
32
+ }
33
+ /** finds the entity name for a given alias, undefined if the alias is not defined */
34
+ findEntityNameByAlias(alias) {
35
+ var _a;
36
+ const upper = alias.toUpperCase();
37
+ for (const entity of this.listEntities()) {
38
+ if (((_a = entity.alias) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === upper) {
39
+ return entity.name;
40
+ }
41
+ }
42
+ return undefined;
43
+ }
44
+ /////////////////////////
45
+ parseSource() {
46
+ var _a;
47
+ if (this.parsedData !== undefined) {
48
+ return this.parsedData;
49
+ }
50
+ this.parsedData = { entities: [] };
51
+ const raw = (_a = this.findSourceFile()) === null || _a === void 0 ? void 0 : _a.getRaw();
52
+ if (raw === undefined) {
53
+ return this.parsedData;
54
+ }
55
+ // BDEF uses "//" for line comments
56
+ const stripped = raw.replace(/\/\/.*$/gm, "");
57
+ // eg. "define behavior for ZI_Booking alias Booking", also "define abstract behavior for ..."
58
+ const regex = /\bdefine\s+(?:\w+\s+)*?behavior\s+for\s+([\w/]+)(?:\s+alias\s+(\w+))?/gi;
59
+ let match = regex.exec(stripped);
60
+ while (match !== null) {
61
+ this.parsedData.entities.push({ name: match[1], alias: match[2] });
62
+ match = regex.exec(stripped);
63
+ }
64
+ return this.parsedData;
65
+ }
19
66
  }
20
67
  exports.BehaviorDefinition = BehaviorDefinition;
21
68
  //# sourceMappingURL=behavior_definition.js.map
@@ -138,19 +138,18 @@ class DataDefinition extends _abstract_object_1.AbstractObject {
138
138
  }
139
139
  for (const e of (expr === null || expr === void 0 ? void 0 : expr.findDirectExpressions(expressions_1.CDSElement)) || []) {
140
140
  let prefix = "";
141
+ let nameInSource = undefined;
141
142
  let found = (_a = e.findDirectExpression(expressions_1.CDSAs)) === null || _a === void 0 ? void 0 : _a.findDirectExpression(expressions_1.CDSName);
142
- if (found === undefined) {
143
- const list = (_b = e.findDirectExpression(expressions_1.CDSPrefixedName)) === null || _b === void 0 ? void 0 : _b.findAllExpressions(expressions_1.CDSName);
144
- if (list) {
145
- if (e.concatTokens().toUpperCase().includes(" REDIRECTED TO ")) {
146
- found = list[0];
147
- }
148
- else {
149
- found = list[list.length - 1];
150
- if (list.length > 1) {
151
- prefix = list[0].concatTokens();
152
- }
153
- }
143
+ const list = (_b = e.findDirectExpression(expressions_1.CDSPrefixedName)) === null || _b === void 0 ? void 0 : _b.findAllExpressions(expressions_1.CDSName);
144
+ if (list !== undefined) {
145
+ const redirected = list.length > 1 && e.concatTokens().toUpperCase().includes(" REDIRECTED TO ");
146
+ if (list.length > 1 && redirected === false) {
147
+ // "prefix.field" is looked up as "field" in "prefix", also when aliased via "as"
148
+ prefix = list[0].concatTokens();
149
+ nameInSource = list[list.length - 1].concatTokens();
150
+ }
151
+ if (found === undefined) {
152
+ found = redirected === true ? list[0] : list[list.length - 1];
154
153
  }
155
154
  }
156
155
  if (found === undefined) {
@@ -172,6 +171,7 @@ class DataDefinition extends _abstract_object_1.AbstractObject {
172
171
  }
173
172
  this.parsedData.fields.push({
174
173
  name: name,
174
+ nameInSource: nameInSource,
175
175
  annotations: annotations,
176
176
  prefix: prefix,
177
177
  key: e.findDirectTokenByText("KEY") !== undefined,
@@ -4,6 +4,7 @@ exports.LockObject = void 0;
4
4
  const basic_1 = require("../abap/types/basic");
5
5
  const ddic_1 = require("../ddic");
6
6
  const _abstract_object_1 = require("./_abstract_object");
7
+ const xml_utils_1 = require("../xml_utils");
7
8
  class LockObject extends _abstract_object_1.AbstractObject {
8
9
  getType() {
9
10
  return "ENQU";
@@ -24,6 +25,11 @@ class LockObject extends _abstract_object_1.AbstractObject {
24
25
  this.parse();
25
26
  return (_a = this.parsedXML) === null || _a === void 0 ? void 0 : _a.primaryTable;
26
27
  }
28
+ getParameters() {
29
+ var _a;
30
+ this.parse();
31
+ return (_a = this.parsedXML) === null || _a === void 0 ? void 0 : _a.parameters;
32
+ }
27
33
  parseType(reg) {
28
34
  var _a;
29
35
  this.parse();
@@ -48,7 +54,7 @@ class LockObject extends _abstract_object_1.AbstractObject {
48
54
  }
49
55
  }
50
56
  parse() {
51
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
57
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
52
58
  if (this.parsedXML) {
53
59
  return { updated: false, runtime: 0 };
54
60
  }
@@ -62,6 +68,18 @@ class LockObject extends _abstract_object_1.AbstractObject {
62
68
  }
63
69
  this.parsedXML.primaryTable = (_f = (_e = (_d = (_c = parsed.abapGit) === null || _c === void 0 ? void 0 : _c["asx:abap"]) === null || _d === void 0 ? void 0 : _d["asx:values"]) === null || _e === void 0 ? void 0 : _e.DD25V) === null || _f === void 0 ? void 0 : _f.ROOTTAB;
64
70
  this.parsedXML.description = (_k = (_j = (_h = (_g = parsed.abapGit) === null || _g === void 0 ? void 0 : _g["asx:abap"]) === null || _h === void 0 ? void 0 : _h["asx:values"]) === null || _j === void 0 ? void 0 : _j.DD25V) === null || _k === void 0 ? void 0 : _k.DDTEXT;
71
+ this.parsedXML.parameters = [];
72
+ const parameters = (_o = (_m = (_l = parsed.abapGit) === null || _l === void 0 ? void 0 : _l["asx:abap"]) === null || _m === void 0 ? void 0 : _m["asx:values"]) === null || _o === void 0 ? void 0 : _o.DD27P_TABLE;
73
+ for (const parameter of (0, xml_utils_1.xmlToArray)(parameters === null || parameters === void 0 ? void 0 : parameters.DD27P)) {
74
+ if (typeof (parameter === null || parameter === void 0 ? void 0 : parameter.VIEWFIELD) !== "string") {
75
+ continue;
76
+ }
77
+ this.parsedXML.parameters.push({
78
+ VIEWFIELD: parameter.VIEWFIELD,
79
+ TABNAME: parameter.TABNAME,
80
+ FIELDNAME: parameter.FIELDNAME,
81
+ });
82
+ }
65
83
  const end = Date.now();
66
84
  return { updated: true, runtime: end - start };
67
85
  }
@@ -75,7 +75,7 @@ class Registry {
75
75
  }
76
76
  static abaplintVersion() {
77
77
  // magic, see build script "version.js"
78
- return "2.120.42";
78
+ return "2.120.44";
79
79
  }
80
80
  getDDICReferences() {
81
81
  return this.ddicReferences;
@@ -46,6 +46,8 @@ class XMLConsistencyConf extends _basic_rule_config_1.BasicRuleConfig {
46
46
  super(...arguments);
47
47
  /** Problem severity for text and translation length checks */
48
48
  this.textAndTranslationLengthSeverity = severity_1.Severity.Error;
49
+ /** Problem severity for data element(DTEL) field checks */
50
+ this.dataElementSeverity = severity_1.Severity.Error;
49
51
  }
50
52
  }
51
53
  exports.XMLConsistencyConf = XMLConsistencyConf;
@@ -62,6 +64,7 @@ class XMLConsistency {
62
64
  * XML is well-formed and parseable
63
65
  * Naming for CLAS and INTF objects
64
66
  * QUAN fields in TABL objects have reference table and field values
67
+ * Lock parameter names in ENQU objects are max 16 characters
65
68
  * Texts and translations do not exceed maximum allowed length.`,
66
69
  tags: [_irule_1.RuleTag.Naming, _irule_1.RuleTag.Syntax],
67
70
  };
@@ -119,6 +122,9 @@ class XMLConsistency {
119
122
  else if (obj instanceof Objects.Table) {
120
123
  issues.push(...this.runTable(obj, file));
121
124
  }
125
+ else if (obj instanceof Objects.LockObject) {
126
+ issues.push(...this.runLockObject(obj, file));
127
+ }
122
128
  if (obj instanceof _abap_object_1.ABAPObject) {
123
129
  issues.push(...this.runTextPool(obj, file));
124
130
  }
@@ -254,7 +260,7 @@ class XMLConsistency {
254
260
  }
255
261
  checkRequiredField(file, fieldName, value) {
256
262
  if (value === undefined || value === "") {
257
- return issue_1.Issue.atRow(file, 1, `Missing required field ${fieldName} in DD04V`, this.getMetadata().key, this.conf.severity);
263
+ return issue_1.Issue.atRow(file, 1, `Missing required field ${fieldName} in DD04V`, this.getMetadata().key, this.conf.dataElementSeverity);
258
264
  }
259
265
  return undefined;
260
266
  }
@@ -302,6 +308,19 @@ class XMLConsistency {
302
308
  }
303
309
  return issues;
304
310
  }
311
+ runLockObject(obj, file) {
312
+ var _a;
313
+ const maxParameterLength = 16;
314
+ const issues = [];
315
+ for (const parameter of (_a = obj.getParameters()) !== null && _a !== void 0 ? _a : []) {
316
+ if (parameter.VIEWFIELD.length > maxParameterLength) {
317
+ const message = `Lock parameter ${parameter.VIEWFIELD} exceeds maximum length of ` +
318
+ `${maxParameterLength} characters (actual: ${parameter.VIEWFIELD.length})`;
319
+ issues.push(issue_1.Issue.atRow(file, 1, message, this.getMetadata().key, this.conf.severity));
320
+ }
321
+ }
322
+ return issues;
323
+ }
305
324
  runTable(obj, file) {
306
325
  var _a, _b;
307
326
  var _c;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/core",
3
- "version": "2.120.42",
3
+ "version": "2.120.44",
4
4
  "description": "abaplint - Core API",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/abaplint.d.ts",