@abaplint/cli 2.120.10 → 2.120.12

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.
Files changed (2) hide show
  1. package/build/cli.js +270 -31
  2. package/package.json +2 -2
package/build/cli.js CHANGED
@@ -4970,7 +4970,7 @@ class For extends combi_1.Expression {
4970
4970
  const itera = (0, combi_1.seq)(_1.InlineFieldDefinition, (0, combi_1.opt)(then), whil);
4971
4971
  const groupBy = (0, combi_1.seq)("GROUP BY", (0, combi_1.alt)(field_chain_1.FieldChain, (0, combi_1.seq)("(", (0, combi_1.plus)(_1.LoopGroupByComponent), ")")), (0, combi_1.opt)((0, combi_1.seq)((0, combi_1.alt)("ASCENDING", "DESCENDING"), (0, combi_1.opt)("AS TEXT"))), (0, combi_1.opt)("WITHOUT MEMBERS"));
4972
4972
  const t = (0, combi_1.alt)(_1.TargetField, _1.TargetFieldSymbol);
4973
- const groups = (0, combi_1.ver)(version_1.Release.v740sp08, (0, combi_1.seq)("GROUPS", t, "OF", t, "IN", _1.Source, (0, combi_1.optPrio)(groupBy)));
4973
+ const groups = (0, combi_1.ver)(version_1.Release.v740sp08, (0, combi_1.seq)("GROUPS", t, "OF", t, "IN", _1.Source, (0, combi_1.optPrio)(groupBy)), { also: combi_1.AlsoIn.OpenABAP });
4974
4974
  const f = (0, combi_1.seq)("FOR", (0, combi_1.alt)(itera, inn, groups), (0, combi_1.optPrio)(_1.Let));
4975
4975
  return (0, combi_1.ver)(version_1.Release.v740sp05, f, { also: combi_1.AlsoIn.OpenABAP });
4976
4976
  }
@@ -5653,7 +5653,8 @@ const combi_1 = __webpack_require__(/*! ../combi */ "../core/build/src/abap/2_st
5653
5653
  const _1 = __webpack_require__(/*! . */ "../core/build/src/abap/2_statements/expressions/index.js");
5654
5654
  class InlineFieldDefinition extends combi_1.Expression {
5655
5655
  getRunnable() {
5656
- return (0, combi_1.altPrio)((0, combi_1.seq)(_1.Field, "=", _1.Source), (0, combi_1.seq)(_1.Field, "TYPE", _1.TypeName));
5656
+ const field = (0, combi_1.altPrio)(_1.Field, _1.FieldSymbol);
5657
+ return (0, combi_1.altPrio)((0, combi_1.seq)(field, "=", _1.Source), (0, combi_1.seq)(_1.Field, "TYPE", _1.TypeName));
5657
5658
  }
5658
5659
  }
5659
5660
  exports.InlineFieldDefinition = InlineFieldDefinition;
@@ -7207,7 +7208,7 @@ const tokens_1 = __webpack_require__(/*! ../../1_lexer/tokens */ "../core/build/
7207
7208
  const version_1 = __webpack_require__(/*! ../../../version */ "../core/build/src/version.js");
7208
7209
  class ReduceNext extends combi_1.Expression {
7209
7210
  getRunnable() {
7210
- const calcAssign = (0, combi_1.ver)(version_1.Release.v754, (0, combi_1.alt)((0, combi_1.seq)((0, combi_1.tok)(tokens_1.WPlus), "="), (0, combi_1.seq)((0, combi_1.tok)(tokens_1.WDash), "="), "/=", "*=", "&&="));
7211
+ const calcAssign = (0, combi_1.ver)(version_1.Release.v754, (0, combi_1.alt)((0, combi_1.seq)((0, combi_1.tok)(tokens_1.WPlus), "="), (0, combi_1.seq)((0, combi_1.tok)(tokens_1.WDash), "="), "/=", "*=", "&&="), { also: combi_1.AlsoIn.OpenABAP });
7211
7212
  const fields = (0, combi_1.seq)(_1.SimpleTarget, (0, combi_1.altPrio)("=", calcAssign), _1.Source);
7212
7213
  return (0, combi_1.seq)("NEXT", (0, combi_1.plus)(fields));
7213
7214
  }
@@ -27355,6 +27356,16 @@ class TypeUtils {
27355
27356
  }
27356
27357
  return false;
27357
27358
  }
27359
+ isCharLikeField(type) {
27360
+ return type instanceof basic_1.CharacterType
27361
+ || type instanceof basic_1.NumericType
27362
+ || type instanceof basic_1.DateType
27363
+ || type instanceof basic_1.TimeType
27364
+ || type instanceof basic_1.CLikeType
27365
+ || type instanceof basic_1.AnyType
27366
+ || type instanceof basic_1.UnknownType
27367
+ || type instanceof basic_1.VoidType;
27368
+ }
27358
27369
  isCharLike(type) {
27359
27370
  if (type === undefined) {
27360
27371
  return false;
@@ -29646,18 +29657,30 @@ exports.ComponentCompare = void 0;
29646
29657
  const Expressions = __importStar(__webpack_require__(/*! ../../2_statements/expressions */ "../core/build/src/abap/2_statements/expressions/index.js"));
29647
29658
  const _syntax_input_1 = __webpack_require__(/*! ../_syntax_input */ "../core/build/src/abap/5_syntax/_syntax_input.js");
29648
29659
  const component_chain_1 = __webpack_require__(/*! ./component_chain */ "../core/build/src/abap/5_syntax/expressions/component_chain.js");
29660
+ const component_name_1 = __webpack_require__(/*! ./component_name */ "../core/build/src/abap/5_syntax/expressions/component_name.js");
29649
29661
  const source_1 = __webpack_require__(/*! ./source */ "../core/build/src/abap/5_syntax/expressions/source.js");
29650
29662
  class ComponentCompare {
29651
- static runSyntax(node, input, type) {
29663
+ static runSyntax(node, input, leftType, rightType) {
29652
29664
  const chain = node.findDirectExpression(Expressions.ComponentChainSimple);
29653
29665
  if (chain === undefined) {
29654
29666
  const message = "ComponentCompare, chain not found";
29655
29667
  input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
29656
29668
  return;
29657
29669
  }
29658
- const fieldType = component_chain_1.ComponentChain.runSyntax(type, chain, input);
29670
+ const fieldType = component_chain_1.ComponentChain.runSyntax(leftType, chain, input);
29659
29671
  for (const s of node.findDirectExpressions(Expressions.Source)) {
29660
- source_1.Source.runSyntax(s, input, fieldType);
29672
+ const fieldChain = s.findDirectExpression(Expressions.FieldChain);
29673
+ const first = fieldChain === null || fieldChain === void 0 ? void 0 : fieldChain.getFirstChild();
29674
+ if (rightType && fieldChain && first) {
29675
+ let sourceType = rightType;
29676
+ if (first.concatTokens().toUpperCase() !== "TABLE_LINE") {
29677
+ sourceType = component_name_1.ComponentName.runSyntax(sourceType, first, input);
29678
+ }
29679
+ component_chain_1.ComponentChain.runSyntax(sourceType, fieldChain, input);
29680
+ }
29681
+ else {
29682
+ source_1.Source.runSyntax(s, input, fieldType);
29683
+ }
29661
29684
  }
29662
29685
  }
29663
29686
  }
@@ -29796,15 +29819,15 @@ exports.ComponentCond = void 0;
29796
29819
  const Expressions = __importStar(__webpack_require__(/*! ../../2_statements/expressions */ "../core/build/src/abap/2_statements/expressions/index.js"));
29797
29820
  const component_compare_1 = __webpack_require__(/*! ./component_compare */ "../core/build/src/abap/5_syntax/expressions/component_compare.js");
29798
29821
  class ComponentCond {
29799
- static runSyntax(node, input, type) {
29822
+ static runSyntax(node, input, leftType, rightType) {
29800
29823
  for (const t of node.findDirectExpressions(Expressions.ComponentCondSub)) {
29801
29824
  const c = t.findDirectExpression(Expressions.ComponentCond);
29802
29825
  if (c) {
29803
- ComponentCond.runSyntax(c, input, type);
29826
+ ComponentCond.runSyntax(c, input, leftType, rightType);
29804
29827
  }
29805
29828
  }
29806
29829
  for (const t of node.findDirectExpressions(Expressions.ComponentCompare)) {
29807
- component_compare_1.ComponentCompare.runSyntax(t, input, type);
29830
+ component_compare_1.ComponentCompare.runSyntax(t, input, leftType, rightType);
29808
29831
  }
29809
29832
  }
29810
29833
  }
@@ -31022,21 +31045,14 @@ class FilterBody {
31022
31045
  if (node === undefined) {
31023
31046
  return targetType;
31024
31047
  }
31025
- let type = undefined;
31048
+ const types = [];
31026
31049
  for (const s of node.findDirectExpressions(Expressions.Source)) {
31027
- if (type === undefined) {
31028
- type = source_1.Source.runSyntax(s, input);
31029
- }
31030
- else {
31031
- source_1.Source.runSyntax(s, input);
31032
- }
31033
- }
31034
- // todo
31035
- if (node.findDirectTokenByText("EXCEPT") === undefined) {
31036
- const rowType = type instanceof basic_1.TableType ? type.getRowType() : undefined;
31037
- component_cond_1.ComponentCond.runSyntax(node.findDirectExpression(Expressions.ComponentCond), input, rowType);
31050
+ types.push(source_1.Source.runSyntax(s, input));
31038
31051
  }
31039
- return type ? type : targetType;
31052
+ const inputRowType = types[0] instanceof basic_1.TableType ? types[0].getRowType() : undefined;
31053
+ const filterRowType = types[1] instanceof basic_1.TableType ? types[1].getRowType() : undefined;
31054
+ component_cond_1.ComponentCond.runSyntax(node.findDirectExpression(Expressions.ComponentCond), input, inputRowType, filterRowType);
31055
+ return types[0] ? types[0] : targetType;
31040
31056
  }
31041
31057
  }
31042
31058
  exports.FilterBody = FilterBody;
@@ -31527,7 +31543,8 @@ class InlineFieldDefinition {
31527
31543
  static runSyntax(node, input, targetType) {
31528
31544
  var _a;
31529
31545
  let type = undefined;
31530
- const field = (_a = node.findDirectExpression(Expressions.Field)) === null || _a === void 0 ? void 0 : _a.getFirstToken();
31546
+ const field = (_a = (node.findDirectExpression(Expressions.Field)
31547
+ || node.findDirectExpression(Expressions.FieldSymbol))) === null || _a === void 0 ? void 0 : _a.getFirstToken();
31531
31548
  if (field === undefined) {
31532
31549
  return undefined;
31533
31550
  }
@@ -35797,7 +35814,11 @@ class ValueBody {
35797
35814
  field_assignment_1.FieldAssignment.runSyntax(s, input, rowType);
35798
35815
  }
35799
35816
  for (const s of foo.findDirectExpressions(Expressions.Source)) {
35800
- source_1.Source.runSyntax(s, input, rowType);
35817
+ const sourceType = source_1.Source.runSyntax(s, input, rowType);
35818
+ if (rowType instanceof basic_1.StringType && sourceType instanceof basic_1.CharacterType) {
35819
+ const message = "VALUE, source type CharacterType not compatible with StringType";
35820
+ input.issues.push((0, _syntax_input_1.syntaxIssue)(input, s.getFirstToken(), message));
35821
+ }
35801
35822
  }
35802
35823
  }
35803
35824
  if (letScoped === true) {
@@ -46629,7 +46650,11 @@ class Write {
46629
46650
  }
46630
46651
  const target = node.findDirectExpression(Expressions.Target);
46631
46652
  if (target) {
46632
- target_1.Target.runSyntax(target, input);
46653
+ const targetType = target_1.Target.runSyntax(target, input);
46654
+ if (new _type_utils_1.TypeUtils(input.scope).isCharLikeField(targetType) === false) {
46655
+ const message = `"${target.getFirstToken().getStr()}" must be a character-like field (data type C, N, D, or T)`;
46656
+ input.issues.push((0, _syntax_input_1.syntaxIssue)(input, target.getFirstToken(), message));
46657
+ }
46633
46658
  }
46634
46659
  }
46635
46660
  }
@@ -51514,6 +51539,7 @@ class ClassDefinition extends _identifier_1.Identifier {
51514
51539
  // perform checks after everything has been initialized
51515
51540
  this.checkInterfaceVisibility(input, node);
51516
51541
  this.checkMethodsFromSuperClasses(input);
51542
+ this.checkClassNameLength(input);
51517
51543
  this.checkMethodNameLength(input);
51518
51544
  this.checkClassConstructorStatic(input);
51519
51545
  }
@@ -51564,6 +51590,12 @@ class ClassDefinition extends _identifier_1.Identifier {
51564
51590
  }
51565
51591
  */
51566
51592
  ///////////////////
51593
+ checkClassNameLength(input) {
51594
+ if (this.getName().length > 30) {
51595
+ const message = `Class name "${this.getName()}" is too long, maximum length is 30 characters`;
51596
+ input.issues.push((0, _syntax_input_1.syntaxIssue)(input, this.getToken(), message));
51597
+ }
51598
+ }
51567
51599
  findSuper(def, input) {
51568
51600
  var _a;
51569
51601
  const token = (_a = def === null || def === void 0 ? void 0 : def.findDirectExpression(expressions_1.SuperClassName)) === null || _a === void 0 ? void 0 : _a.getFirstToken();
@@ -56040,7 +56072,7 @@ exports.DDLAspect = DDLAspect;
56040
56072
  "use strict";
56041
56073
 
56042
56074
  Object.defineProperty(exports, "__esModule", ({ value: true }));
56043
- exports.DDLValueHelp = exports.DDLForeignKey = exports.DDLForeignKeyTarget = void 0;
56075
+ exports.DDLReference = exports.DDLValueHelp = exports.DDLForeignKey = exports.DDLForeignKeyTarget = void 0;
56044
56076
  const combi_1 = __webpack_require__(/*! ../../abap/2_statements/combi */ "../core/build/src/abap/2_statements/combi.js");
56045
56077
  const ddl_literal_1 = __webpack_require__(/*! ./ddl_literal */ "../core/build/src/ddl/expressions/ddl_literal.js");
56046
56078
  const ddl_name_1 = __webpack_require__(/*! ./ddl_name */ "../core/build/src/ddl/expressions/ddl_name.js");
@@ -56064,6 +56096,12 @@ class DDLValueHelp extends combi_1.Expression {
56064
56096
  }
56065
56097
  }
56066
56098
  exports.DDLValueHelp = DDLValueHelp;
56099
+ class DDLReference extends combi_1.Expression {
56100
+ getRunnable() {
56101
+ return (0, combi_1.seq)("WITH", "REFERENCE", "TABLE", ddl_name_1.DDLName, "AND", "REFERENCE", "FIELD", ddl_name_1.DDLName);
56102
+ }
56103
+ }
56104
+ exports.DDLReference = DDLReference;
56067
56105
  //# sourceMappingURL=ddl_clauses.js.map
56068
56106
 
56069
56107
  /***/ },
@@ -56339,7 +56377,7 @@ const ddl_name_1 = __webpack_require__(/*! ./ddl_name */ "../core/build/src/ddl/
56339
56377
  const ddl_type_1 = __webpack_require__(/*! ./ddl_type */ "../core/build/src/ddl/expressions/ddl_type.js");
56340
56378
  class DDLTableField extends combi_1.Expression {
56341
56379
  getRunnable() {
56342
- const trailingClause = (0, combi_1.alt)(ddl_clauses_1.DDLForeignKey, ddl_clauses_1.DDLValueHelp);
56380
+ const trailingClause = (0, combi_1.alt)(ddl_clauses_1.DDLForeignKey, ddl_clauses_1.DDLReference, ddl_clauses_1.DDLValueHelp);
56343
56381
  return (0, combi_1.seq)((0, combi_1.star)(expressions_1.CDSAnnotation), (0, combi_1.optPrio)("KEY"), ddl_name_1.DDLName, ":", ddl_type_1.DDLType, (0, combi_1.optPrio)("NOT NULL"), (0, combi_1.star)(trailingClause), ";");
56344
56382
  }
56345
56383
  }
@@ -67561,6 +67599,13 @@ class Table extends _abstract_object_1.AbstractObject {
67561
67599
  }
67562
67600
  return (_a = this.parsedData) === null || _a === void 0 ? void 0 : _a.secondaryIndexes;
67563
67601
  }
67602
+ getFields() {
67603
+ var _a;
67604
+ if (this.parsedData === undefined) {
67605
+ this.parseXML();
67606
+ }
67607
+ return (_a = this.parsedData) === null || _a === void 0 ? void 0 : _a.fields;
67608
+ }
67564
67609
  getAllowedNaming() {
67565
67610
  let length = 30;
67566
67611
  const regex = /^((\/[A-Z_\d]{3,8}\/)|[a-zA-Z0-9]{3}|CI_)\w+$/;
@@ -67613,9 +67658,13 @@ class Table extends _abstract_object_1.AbstractObject {
67613
67658
  && this.parsedData.dataClass === "USER3") {
67614
67659
  return new Types.UnknownType("Data class = USER3 not allowed in cloud");
67615
67660
  }
67616
- if (this.getTableCategory() === TableCategory.Transparent
67617
- && this.listKeys(reg).length === 0) {
67618
- return new Types.UnknownType("Table " + this.getName() + " has no key fields");
67661
+ if (this.getTableCategory() === TableCategory.Transparent) {
67662
+ if (this.listKeys(reg).length === 0) {
67663
+ return new Types.UnknownType("Table " + this.getName() + " has no key fields");
67664
+ }
67665
+ else if (this.keyFieldsNotFirst()) {
67666
+ return new Types.UnknownType("Table " + this.getName() + " key fields must be first");
67667
+ }
67619
67668
  }
67620
67669
  if (this.parsedType) {
67621
67670
  return this.parsedType;
@@ -67791,6 +67840,21 @@ class Table extends _abstract_object_1.AbstractObject {
67791
67840
  return this.parsedData.enhancementCategory;
67792
67841
  }
67793
67842
  ///////////////
67843
+ keyFieldsNotFirst() {
67844
+ var _a;
67845
+ let seenNonKey = false;
67846
+ for (const field of ((_a = this.parsedData) === null || _a === void 0 ? void 0 : _a.fields) || []) {
67847
+ if (field.KEYFLAG === "X") {
67848
+ if (seenNonKey === true) {
67849
+ return true;
67850
+ }
67851
+ }
67852
+ else {
67853
+ seenNonKey = true;
67854
+ }
67855
+ }
67856
+ return false;
67857
+ }
67794
67858
  parseXML() {
67795
67859
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
67796
67860
  const parsed = super.parseRaw2();
@@ -67827,6 +67891,8 @@ class Table extends _abstract_object_1.AbstractObject {
67827
67891
  KEYFLAG: field.KEYFLAG,
67828
67892
  GROUPNAME: field.GROUPNAME,
67829
67893
  CHECKTABLE: field.CHECKTABLE,
67894
+ REFTABLE: field.REFTABLE,
67895
+ REFFIELD: field.REFFIELD,
67830
67896
  REFTYPE: field.REFTYPE,
67831
67897
  DDTEXT: field.DDTEXT,
67832
67898
  });
@@ -69365,7 +69431,7 @@ class Registry {
69365
69431
  }
69366
69432
  static abaplintVersion() {
69367
69433
  // magic, see build script "version.js"
69368
- return "2.120.10";
69434
+ return "2.120.12";
69369
69435
  }
69370
69436
  getDDICReferences() {
69371
69437
  return this.ddicReferences;
@@ -83165,6 +83231,7 @@ __exportStar(__webpack_require__(/*! ./no_comments_between_methods */ "../core/b
83165
83231
  __exportStar(__webpack_require__(/*! ./no_external_form_calls */ "../core/build/src/rules/no_external_form_calls.js"), exports);
83166
83232
  __exportStar(__webpack_require__(/*! ./no_inline_in_optional_branches */ "../core/build/src/rules/no_inline_in_optional_branches.js"), exports);
83167
83233
  __exportStar(__webpack_require__(/*! ./no_macros */ "../core/build/src/rules/no_macros.js"), exports);
83234
+ __exportStar(__webpack_require__(/*! ./no_mandt_in_database_operations */ "../core/build/src/rules/no_mandt_in_database_operations.js"), exports);
83168
83235
  __exportStar(__webpack_require__(/*! ./no_prefixes */ "../core/build/src/rules/no_prefixes.js"), exports);
83169
83236
  __exportStar(__webpack_require__(/*! ./no_public_attributes */ "../core/build/src/rules/no_public_attributes.js"), exports);
83170
83237
  __exportStar(__webpack_require__(/*! ./no_yoda_conditions */ "../core/build/src/rules/no_yoda_conditions.js"), exports);
@@ -87642,6 +87709,153 @@ exports.NoMacros = NoMacros;
87642
87709
 
87643
87710
  /***/ },
87644
87711
 
87712
+ /***/ "../core/build/src/rules/no_mandt_in_database_operations.js"
87713
+ /*!******************************************************************!*\
87714
+ !*** ../core/build/src/rules/no_mandt_in_database_operations.js ***!
87715
+ \******************************************************************/
87716
+ (__unused_webpack_module, exports, __webpack_require__) {
87717
+
87718
+ "use strict";
87719
+
87720
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
87721
+ if (k2 === undefined) k2 = k;
87722
+ var desc = Object.getOwnPropertyDescriptor(m, k);
87723
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
87724
+ desc = { enumerable: true, get: function() { return m[k]; } };
87725
+ }
87726
+ Object.defineProperty(o, k2, desc);
87727
+ }) : (function(o, m, k, k2) {
87728
+ if (k2 === undefined) k2 = k;
87729
+ o[k2] = m[k];
87730
+ }));
87731
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
87732
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
87733
+ }) : function(o, v) {
87734
+ o["default"] = v;
87735
+ });
87736
+ var __importStar = (this && this.__importStar) || (function () {
87737
+ var ownKeys = function(o) {
87738
+ ownKeys = Object.getOwnPropertyNames || function (o) {
87739
+ var ar = [];
87740
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
87741
+ return ar;
87742
+ };
87743
+ return ownKeys(o);
87744
+ };
87745
+ return function (mod) {
87746
+ if (mod && mod.__esModule) return mod;
87747
+ var result = {};
87748
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
87749
+ __setModuleDefault(result, mod);
87750
+ return result;
87751
+ };
87752
+ })();
87753
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
87754
+ exports.NoMandtInDatabaseOperations = exports.NoMandtInDatabaseOperationsConf = void 0;
87755
+ const Expressions = __importStar(__webpack_require__(/*! ../abap/2_statements/expressions */ "../core/build/src/abap/2_statements/expressions/index.js"));
87756
+ const Statements = __importStar(__webpack_require__(/*! ../abap/2_statements/statements */ "../core/build/src/abap/2_statements/statements/index.js"));
87757
+ const issue_1 = __webpack_require__(/*! ../issue */ "../core/build/src/issue.js");
87758
+ const _abap_rule_1 = __webpack_require__(/*! ./_abap_rule */ "../core/build/src/rules/_abap_rule.js");
87759
+ const _basic_rule_config_1 = __webpack_require__(/*! ./_basic_rule_config */ "../core/build/src/rules/_basic_rule_config.js");
87760
+ const _irule_1 = __webpack_require__(/*! ./_irule */ "../core/build/src/rules/_irule.js");
87761
+ class NoMandtInDatabaseOperationsConf extends _basic_rule_config_1.BasicRuleConfig {
87762
+ }
87763
+ exports.NoMandtInDatabaseOperationsConf = NoMandtInDatabaseOperationsConf;
87764
+ class NoMandtInDatabaseOperations extends _abap_rule_1.ABAPRule {
87765
+ constructor() {
87766
+ super(...arguments);
87767
+ this.conf = new NoMandtInDatabaseOperationsConf();
87768
+ }
87769
+ getMetadata() {
87770
+ return {
87771
+ key: "no_mandt_in_database_operations",
87772
+ title: "No MANDT in database operations",
87773
+ shortDescription: "Do not specify the client in database operations; the ABAP runtime handles it automatically.",
87774
+ extendedInformation: "Only check for the name MANDT, not for the field type. The rule does not check for dynamic SQL.",
87775
+ tags: [_irule_1.RuleTag.SingleFile, _irule_1.RuleTag.Syntax],
87776
+ badExample: `SELECT * FROM zcustomers
87777
+ CLIENT SPECIFIED
87778
+ WHERE mandt = @sy-mandt
87779
+ INTO TABLE @DATA(customers).`,
87780
+ goodExample: `SELECT * FROM zcustomers
87781
+ INTO TABLE @DATA(customers).`,
87782
+ };
87783
+ }
87784
+ getConfig() {
87785
+ return this.conf;
87786
+ }
87787
+ setConfig(conf) {
87788
+ this.conf = conf;
87789
+ }
87790
+ runParsed(file) {
87791
+ const issues = [];
87792
+ for (const statement of file.getStatements()) {
87793
+ if (this.isDatabaseOperation(statement) === false) {
87794
+ continue;
87795
+ }
87796
+ const mandt = this.findMandtInCondition(statement);
87797
+ if (mandt !== undefined) {
87798
+ const issue = issue_1.Issue.atToken(file, mandt.getFirstToken(), this.getMetadata().title, this.getMetadata().key, this.conf.severity);
87799
+ issues.push(issue);
87800
+ continue;
87801
+ }
87802
+ const explicitClient = this.findExplicitClient(statement);
87803
+ if (explicitClient !== undefined) {
87804
+ const issue = issue_1.Issue.atToken(file, explicitClient, this.getMetadata().title, this.getMetadata().key, this.conf.severity);
87805
+ issues.push(issue);
87806
+ }
87807
+ }
87808
+ return issues;
87809
+ }
87810
+ isDatabaseOperation(statement) {
87811
+ const type = statement.get();
87812
+ return type instanceof Statements.DeleteDatabase
87813
+ || type instanceof Statements.InsertDatabase
87814
+ || type instanceof Statements.MergeDatabase
87815
+ || type instanceof Statements.ModifyDatabase
87816
+ || type instanceof Statements.OpenCursor
87817
+ || type instanceof Statements.Select
87818
+ || type instanceof Statements.SelectLoop
87819
+ || type instanceof Statements.UpdateDatabase
87820
+ || type instanceof Statements.With
87821
+ || type instanceof Statements.WithLoop;
87822
+ }
87823
+ findMandtInCondition(statement) {
87824
+ for (const condition of statement.findAllExpressions(Expressions.SQLCond)) {
87825
+ const fields = condition.findAllExpressionsMulti([
87826
+ Expressions.SQLFieldName,
87827
+ Expressions.SQLAliasField,
87828
+ ]);
87829
+ for (const field of fields) {
87830
+ const name = field.concatTokens().toUpperCase();
87831
+ if (name === "MANDT" || name.endsWith("~MANDT")) {
87832
+ return field;
87833
+ }
87834
+ }
87835
+ }
87836
+ return undefined;
87837
+ }
87838
+ findExplicitClient(statement) {
87839
+ var _a, _b;
87840
+ const tokens = statement.getTokens();
87841
+ for (let index = 0; index < tokens.length; index++) {
87842
+ const current = tokens[index].getStr().toUpperCase();
87843
+ const next = (_a = tokens[index + 1]) === null || _a === void 0 ? void 0 : _a.getStr().toUpperCase();
87844
+ const afterNext = (_b = tokens[index + 2]) === null || _b === void 0 ? void 0 : _b.getStr().toUpperCase();
87845
+ if ((current === "CLIENT" && next === "SPECIFIED")
87846
+ || (current === "USING" && (next === "CLIENT" || next === "CLIENTS"))
87847
+ || (current === "USING" && next === "ALL" && afterNext === "CLIENTS")) {
87848
+ return current === "CLIENT" ? tokens[index] : tokens[index + (next === "ALL" ? 2 : 1)];
87849
+ }
87850
+ }
87851
+ return undefined;
87852
+ }
87853
+ }
87854
+ exports.NoMandtInDatabaseOperations = NoMandtInDatabaseOperations;
87855
+ //# sourceMappingURL=no_mandt_in_database_operations.js.map
87856
+
87857
+ /***/ },
87858
+
87645
87859
  /***/ "../core/build/src/rules/no_prefixes.js"
87646
87860
  /*!**********************************************!*\
87647
87861
  !*** ../core/build/src/rules/no_prefixes.js ***!
@@ -98382,6 +98596,7 @@ class XMLConsistency {
98382
98596
  extendedInformation: `Checks:
98383
98597
  * XML is well-formed and parseable
98384
98598
  * Naming for CLAS and INTF objects
98599
+ * QUAN fields in TABL objects have reference table and field values
98385
98600
  * Texts and translations do not exceed maximum allowed length.`,
98386
98601
  tags: [_irule_1.RuleTag.Naming, _irule_1.RuleTag.Syntax],
98387
98602
  };
@@ -98396,6 +98611,7 @@ class XMLConsistency {
98396
98611
  return this;
98397
98612
  }
98398
98613
  run(obj) {
98614
+ var _a;
98399
98615
  const issues = [];
98400
98616
  const file = obj.getXMLFile();
98401
98617
  if (file === undefined) {
@@ -98407,6 +98623,14 @@ class XMLConsistency {
98407
98623
  if (res !== true) {
98408
98624
  issues.push(issue_1.Issue.atRow(file, 1, "XML parser error: " + res.err.msg, this.getMetadata().key, this.conf.severity));
98409
98625
  }
98626
+ else {
98627
+ for (const attribute of ["version", "serializer_version"]) {
98628
+ const value = (_a = xml.match(new RegExp(`<abapGit\\b[^>]*\\b${attribute}="([^"]+)"`))) === null || _a === void 0 ? void 0 : _a[1];
98629
+ if (value !== undefined && value.match(/^v\d\.\d\.\d$/) === null) {
98630
+ issues.push(issue_1.Issue.atRow(file, 1, `Unexpected abapGit ${attribute} "${value}"`, this.getMetadata().key, this.conf.severity));
98631
+ }
98632
+ }
98633
+ }
98410
98634
  }
98411
98635
  // todo, have some XML validation in each object?
98412
98636
  if (obj instanceof Objects.Class) {
@@ -98427,6 +98651,9 @@ class XMLConsistency {
98427
98651
  else if (obj instanceof Objects.MessageClass) {
98428
98652
  issues.push(...this.runMessageClass(obj, file));
98429
98653
  }
98654
+ else if (obj instanceof Objects.Table) {
98655
+ issues.push(...this.runTable(obj, file));
98656
+ }
98430
98657
  if (obj instanceof _abap_object_1.ABAPObject) {
98431
98658
  issues.push(...this.runTextPool(obj, file));
98432
98659
  }
@@ -98570,6 +98797,18 @@ class XMLConsistency {
98570
98797
  }
98571
98798
  return issues;
98572
98799
  }
98800
+ runTable(obj, file) {
98801
+ var _a, _b;
98802
+ var _c;
98803
+ const issues = [];
98804
+ for (const field of (_c = obj.getFields()) !== null && _c !== void 0 ? _c : []) {
98805
+ if (field.DATATYPE === "QUAN" && (!((_a = field.REFTABLE) === null || _a === void 0 ? void 0 : _a.trim()) || !((_b = field.REFFIELD) === null || _b === void 0 ? void 0 : _b.trim()))) {
98806
+ const message = `QUAN field ${field.FIELDNAME} must have REFTABLE and REFFIELD set`;
98807
+ issues.push(issue_1.Issue.atRow(file, 1, message, this.getMetadata().key, this.conf.severity));
98808
+ }
98809
+ }
98810
+ return issues;
98811
+ }
98573
98812
  }
98574
98813
  exports.XMLConsistency = XMLConsistency;
98575
98814
  //# sourceMappingURL=xml_consistency.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/cli",
3
- "version": "2.120.10",
3
+ "version": "2.120.12",
4
4
  "description": "abaplint - Command Line Interface",
5
5
  "funding": "https://github.com/sponsors/larshp",
6
6
  "bin": {
@@ -39,7 +39,7 @@
39
39
  },
40
40
  "homepage": "https://abaplint.org",
41
41
  "devDependencies": {
42
- "@abaplint/core": "^2.120.10",
42
+ "@abaplint/core": "^2.120.12",
43
43
  "@types/chai": "^4.3.20",
44
44
  "@types/minimist": "^1.2.5",
45
45
  "@types/mocha": "^10.0.10",