@abaplint/transpiler-cli 2.8.24 → 2.8.26

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/bundle.js +812 -116
  2. package/package.json +4 -4
package/build/bundle.js CHANGED
@@ -535,6 +535,7 @@ class LexerStream {
535
535
  this.row = this.row + 1;
536
536
  }
537
537
  if (this.offset === this.raw.length) {
538
+ this.col = this.col - 1;
538
539
  return false;
539
540
  }
540
541
  this.col = this.col + 1;
@@ -1920,7 +1921,7 @@ class Star {
1920
1921
  return this.sta.getUsing();
1921
1922
  }
1922
1923
  run(r) {
1923
- const result = r;
1924
+ let result = r;
1924
1925
  try {
1925
1926
  let res = r;
1926
1927
  let input = [];
@@ -1930,7 +1931,13 @@ class Star {
1930
1931
  if (res.length === 0) {
1931
1932
  break;
1932
1933
  }
1933
- result.push(...res);
1934
+ if (res.length > 1000) {
1935
+ // avoid stack overflow
1936
+ result = result.concat(res);
1937
+ }
1938
+ else {
1939
+ result.push(...res);
1940
+ }
1934
1941
  }
1935
1942
  }
1936
1943
  catch (err) {
@@ -2063,7 +2070,7 @@ class Sequence {
2063
2070
  return this.list.reduce((a, c) => { return a.concat(c.getUsing()); }, []);
2064
2071
  }
2065
2072
  run(r) {
2066
- const result = [];
2073
+ let result = [];
2067
2074
  for (const input of r) {
2068
2075
  let temp = [input];
2069
2076
  let match = true;
@@ -2075,7 +2082,13 @@ class Sequence {
2075
2082
  }
2076
2083
  }
2077
2084
  if (match === true) {
2078
- result.push(...temp);
2085
+ if (temp.length > 1000) {
2086
+ // avoid stack overflow
2087
+ result = result.concat(temp);
2088
+ }
2089
+ else {
2090
+ result.push(...temp);
2091
+ }
2079
2092
  }
2080
2093
  }
2081
2094
  return result;
@@ -7831,9 +7844,8 @@ class Target extends combi_1.Expression {
7831
7844
  const attr = (0, combi_1.seq)((0, combi_1.tok)(tokens_1.InstanceArrow), attribute_name_1.AttributeName);
7832
7845
  const comp = (0, combi_1.seq)((0, combi_1.tok)(tokens_1.Dash), _1.ComponentName);
7833
7846
  const something = (0, combi_1.starPrio)((0, combi_1.altPrio)(dereference_1.Dereference, attr, comp, _1.TableExpression));
7834
- const cast = (0, combi_1.seq)((0, combi_1.altPrio)(_1.Cast, _1.NewObject), _1.Arrow, _1.FieldAll);
7835
7847
  const clas = (0, combi_1.seq)(_1.ClassName, (0, combi_1.tok)(tokens_1.StaticArrow), attribute_name_1.AttributeName);
7836
- const start = (0, combi_1.altPrio)(cast, clas, _1.TargetField, _1.TargetFieldSymbol);
7848
+ const start = (0, combi_1.altPrio)(_1.Cast, _1.NewObject, clas, _1.TargetField, _1.TargetFieldSymbol);
7837
7849
  const fields = (0, combi_1.seq)((0, combi_1.optPrio)(_1.FieldOffset), (0, combi_1.optPrio)(_1.FieldLength));
7838
7850
  const optional = (0, combi_1.altPrio)(_1.TableBody, fields);
7839
7851
  return (0, combi_1.altPrio)(_1.InlineData, _1.InlineFS, (0, combi_1.seq)(start, something, optional));
@@ -10826,9 +10838,9 @@ const expressions_1 = __webpack_require__(/*! ../expressions */ "./node_modules/
10826
10838
  const version_1 = __webpack_require__(/*! ../../../version */ "./node_modules/@abaplint/core/build/src/version.js");
10827
10839
  class EditorCall {
10828
10840
  getMatcher() {
10829
- const title = (0, combi_1.seq)("TITLE", expressions_1.Source);
10841
+ const title = (0, combi_1.seq)("TITLE", expressions_1.SimpleSource3);
10830
10842
  const options = (0, combi_1.per)("DISPLAY-MODE", title);
10831
- const ret = (0, combi_1.seq)("EDITOR-CALL FOR", (0, combi_1.opt)("REPORT"), expressions_1.Source, (0, combi_1.opt)(options));
10843
+ const ret = (0, combi_1.seq)("EDITOR-CALL FOR", (0, combi_1.optPrio)("REPORT"), expressions_1.Source, (0, combi_1.optPrio)(options));
10832
10844
  return (0, combi_1.verNot)(version_1.Version.Cloud, ret);
10833
10845
  }
10834
10846
  }
@@ -16900,7 +16912,7 @@ class Sequence {
16900
16912
  }
16901
16913
  run(statements, parent) {
16902
16914
  let inn = statements;
16903
- const out = [];
16915
+ let out = [];
16904
16916
  for (const i of this.list) {
16905
16917
  const match = i.run(inn, parent);
16906
16918
  if (match.error) {
@@ -16912,7 +16924,14 @@ class Sequence {
16912
16924
  errorMatched: out.length,
16913
16925
  };
16914
16926
  }
16915
- out.push(...match.matched);
16927
+ if (match.matched.length < 100) {
16928
+ out.push(...match.matched);
16929
+ }
16930
+ else {
16931
+ // avoid using the spread operator, it might trigger "Maximum call stack size exceeded"
16932
+ // when the number of matched elements is very large
16933
+ out = out.concat(match.matched);
16934
+ }
16916
16935
  inn = match.unmatched;
16917
16936
  }
16918
16937
  return {
@@ -17044,7 +17063,7 @@ class Star {
17044
17063
  }
17045
17064
  run(statements, parent) {
17046
17065
  let inn = statements;
17047
- const out = [];
17066
+ let out = [];
17048
17067
  while (true) {
17049
17068
  if (inn.length === 0) {
17050
17069
  return {
@@ -17076,7 +17095,14 @@ class Star {
17076
17095
  };
17077
17096
  }
17078
17097
  }
17079
- out.push(...match.matched);
17098
+ if (match.matched.length < 100) {
17099
+ out.push(...match.matched);
17100
+ }
17101
+ else {
17102
+ // avoid using the spread operator, it might trigger "Maximum call stack size exceeded"
17103
+ // when the number of matched elements is very large
17104
+ out = out.concat(match.matched);
17105
+ }
17080
17106
  inn = match.unmatched;
17081
17107
  }
17082
17108
  }
@@ -21617,6 +21643,16 @@ class TypeUtils {
21617
21643
  return false;
21618
21644
  }
21619
21645
  }
21646
+ else if (source instanceof basic_1.TableType) {
21647
+ if (target instanceof basic_1.TableType) {
21648
+ return this.isAssignableStrict(source.getRowType(), target.getRowType());
21649
+ }
21650
+ else if (target instanceof basic_1.UnknownType
21651
+ || target instanceof basic_1.AnyType
21652
+ || target instanceof basic_1.VoidType) {
21653
+ return true;
21654
+ }
21655
+ }
21620
21656
  return this.isAssignable(source, target);
21621
21657
  }
21622
21658
  isAssignable(source, target) {
@@ -22849,6 +22885,7 @@ const Expressions = __webpack_require__(/*! ../../2_statements/expressions */ ".
22849
22885
  const source_1 = __webpack_require__(/*! ./source */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/source.js");
22850
22886
  const _type_utils_1 = __webpack_require__(/*! ../_type_utils */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/_type_utils.js");
22851
22887
  const basic_types_1 = __webpack_require__(/*! ../basic_types */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/basic_types.js");
22888
+ const _reference_1 = __webpack_require__(/*! ../_reference */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/_reference.js");
22852
22889
  class Cast {
22853
22890
  runSyntax(node, scope, targetType, filename) {
22854
22891
  const sourceNode = node.findDirectExpression(Expressions.Source);
@@ -22875,6 +22912,7 @@ class Cast {
22875
22912
  const found = scope.findObjectDefinition(typeName);
22876
22913
  if (found) {
22877
22914
  tt = new basic_1.ObjectReferenceType(found, { qualifiedName: typeName });
22915
+ scope.addReference(typeExpression.getFirstToken(), found, _reference_1.ReferenceType.ObjectOrientedReference, filename);
22878
22916
  }
22879
22917
  }
22880
22918
  else {
@@ -25432,6 +25470,7 @@ const _scope_type_1 = __webpack_require__(/*! ../_scope_type */ "./node_modules/
25432
25470
  const sql_source_1 = __webpack_require__(/*! ./sql_source */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/sql_source.js");
25433
25471
  const sql_compare_1 = __webpack_require__(/*! ./sql_compare */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/sql_compare.js");
25434
25472
  const sql_order_by_1 = __webpack_require__(/*! ./sql_order_by */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/sql_order_by.js");
25473
+ const dynamic_1 = __webpack_require__(/*! ./dynamic */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/dynamic.js");
25435
25474
  const isSimple = /^\w+$/;
25436
25475
  class Select {
25437
25476
  runSyntax(node, scope, filename, skipImplicitInto = false) {
@@ -25442,7 +25481,7 @@ class Select {
25442
25481
  if (from === undefined) {
25443
25482
  throw new Error(`Missing FROM`);
25444
25483
  }
25445
- const fields = this.findFields(node);
25484
+ const fields = this.findFields(node, scope, filename);
25446
25485
  if (fields.length === 0
25447
25486
  && node.findDirectExpression(Expressions.SQLFieldListLoop) === undefined) {
25448
25487
  throw new Error(`fields missing`);
@@ -25600,17 +25639,20 @@ class Select {
25600
25639
  }
25601
25640
  return new basic_1.VoidType("SELECT_todo");
25602
25641
  }
25603
- findFields(node) {
25604
- var _a;
25642
+ findFields(node, scope, filename) {
25643
+ var _a, _b;
25605
25644
  let expr = undefined;
25606
25645
  const ret = [];
25607
25646
  expr = node.findFirstExpression(Expressions.SQLFieldList);
25608
25647
  if (expr === undefined) {
25609
25648
  expr = node.findDirectExpression(Expressions.SQLFieldListLoop);
25610
25649
  }
25650
+ if (((_a = expr === null || expr === void 0 ? void 0 : expr.getFirstChild()) === null || _a === void 0 ? void 0 : _a.get()) instanceof Expressions.Dynamic) {
25651
+ new dynamic_1.Dynamic().runSyntax(expr.getFirstChild(), scope, filename);
25652
+ }
25611
25653
  for (const field of (expr === null || expr === void 0 ? void 0 : expr.findDirectExpressionsMulti([Expressions.SQLField, Expressions.SQLFieldName])) || []) {
25612
25654
  let code = field.concatTokens().toUpperCase();
25613
- const as = ((_a = field.findDirectExpression(Expressions.SQLAsName)) === null || _a === void 0 ? void 0 : _a.concatTokens()) || "";
25655
+ const as = ((_b = field.findDirectExpression(Expressions.SQLAsName)) === null || _b === void 0 ? void 0 : _b.concatTokens()) || "";
25614
25656
  if (as !== "") {
25615
25657
  code = code.replace(" AS " + as, "");
25616
25658
  }
@@ -26052,13 +26094,18 @@ exports.SQLCompare = void 0;
26052
26094
  const Expressions = __webpack_require__(/*! ../../2_statements/expressions */ "./node_modules/@abaplint/core/build/src/abap/2_statements/expressions/index.js");
26053
26095
  const nodes_1 = __webpack_require__(/*! ../../nodes */ "./node_modules/@abaplint/core/build/src/abap/nodes/index.js");
26054
26096
  const basic_1 = __webpack_require__(/*! ../../types/basic */ "./node_modules/@abaplint/core/build/src/abap/types/basic/index.js");
26097
+ const dynamic_1 = __webpack_require__(/*! ./dynamic */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/dynamic.js");
26055
26098
  const source_1 = __webpack_require__(/*! ./source */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/source.js");
26056
26099
  const sql_source_1 = __webpack_require__(/*! ./sql_source */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/sql_source.js");
26057
26100
  class SQLCompare {
26058
26101
  runSyntax(node, scope, filename, tables) {
26059
- var _a;
26102
+ var _a, _b;
26060
26103
  let sourceType;
26061
26104
  let token;
26105
+ if (((_a = node.getFirstChild()) === null || _a === void 0 ? void 0 : _a.get()) instanceof Expressions.Dynamic) {
26106
+ new dynamic_1.Dynamic().runSyntax(node.getFirstChild(), scope, filename);
26107
+ return;
26108
+ }
26062
26109
  for (const s of node.findAllExpressions(Expressions.SimpleSource3)) {
26063
26110
  new source_1.Source().runSyntax(s, scope, filename);
26064
26111
  }
@@ -26084,7 +26131,7 @@ class SQLCompare {
26084
26131
  }
26085
26132
  }
26086
26133
  }
26087
- const fieldName = (_a = node.findDirectExpression(Expressions.SQLFieldName)) === null || _a === void 0 ? void 0 : _a.concatTokens();
26134
+ const fieldName = (_b = node.findDirectExpression(Expressions.SQLFieldName)) === null || _b === void 0 ? void 0 : _b.concatTokens();
26088
26135
  if (fieldName && sourceType && token) {
26089
26136
  // check compatibility for rule sql_value_conversion
26090
26137
  const targetType = this.findType(fieldName, tables, scope);
@@ -26397,6 +26444,7 @@ const _reference_1 = __webpack_require__(/*! ../_reference */ "./node_modules/@a
26397
26444
  const table_expression_1 = __webpack_require__(/*! ./table_expression */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/table_expression.js");
26398
26445
  const expressions_1 = __webpack_require__(/*! ../../2_statements/expressions */ "./node_modules/@abaplint/core/build/src/abap/2_statements/expressions/index.js");
26399
26446
  const field_length_1 = __webpack_require__(/*! ./field_length */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/field_length.js");
26447
+ const cast_1 = __webpack_require__(/*! ./cast */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/cast.js");
26400
26448
  class Target {
26401
26449
  runSyntax(node, scope, filename) {
26402
26450
  const concat = node.concatTokens();
@@ -26528,6 +26576,13 @@ class Target {
26528
26576
  return new unknown_type_1.UnknownType(name + " unknown, Target");
26529
26577
  }
26530
26578
  }
26579
+ else if (node.get() instanceof Expressions.Cast && node instanceof nodes_1.ExpressionNode) {
26580
+ const ret = new cast_1.Cast().runSyntax(node, scope, undefined, filename);
26581
+ if (ret instanceof unknown_type_1.UnknownType) {
26582
+ throw new Error("CAST, uknown type");
26583
+ }
26584
+ return ret;
26585
+ }
26531
26586
  return new unknown_type_1.UnknownType("unknown target type");
26532
26587
  }
26533
26588
  }
@@ -28823,6 +28878,33 @@ exports.Do = Do;
28823
28878
 
28824
28879
  /***/ }),
28825
28880
 
28881
+ /***/ "./node_modules/@abaplint/core/build/src/abap/5_syntax/statements/editor_call.js":
28882
+ /*!***************************************************************************************!*\
28883
+ !*** ./node_modules/@abaplint/core/build/src/abap/5_syntax/statements/editor_call.js ***!
28884
+ \***************************************************************************************/
28885
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
28886
+
28887
+ "use strict";
28888
+
28889
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
28890
+ exports.EditorCall = void 0;
28891
+ const Expressions = __webpack_require__(/*! ../../2_statements/expressions */ "./node_modules/@abaplint/core/build/src/abap/2_statements/expressions/index.js");
28892
+ const source_1 = __webpack_require__(/*! ../expressions/source */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/source.js");
28893
+ class EditorCall {
28894
+ runSyntax(node, scope, filename) {
28895
+ for (const s of node.findDirectExpressions(Expressions.Source)) {
28896
+ new source_1.Source().runSyntax(s, scope, filename);
28897
+ }
28898
+ for (const t of node.findDirectExpressions(Expressions.SimpleSource3)) {
28899
+ new source_1.Source().runSyntax(t, scope, filename);
28900
+ }
28901
+ }
28902
+ }
28903
+ exports.EditorCall = EditorCall;
28904
+ //# sourceMappingURL=editor_call.js.map
28905
+
28906
+ /***/ }),
28907
+
28826
28908
  /***/ "./node_modules/@abaplint/core/build/src/abap/5_syntax/statements/else_if.js":
28827
28909
  /*!***********************************************************************************!*\
28828
28910
  !*** ./node_modules/@abaplint/core/build/src/abap/5_syntax/statements/else_if.js ***!
@@ -32636,6 +32718,7 @@ const close_dataset_1 = __webpack_require__(/*! ./statements/close_dataset */ ".
32636
32718
  const get_run_time_1 = __webpack_require__(/*! ./statements/get_run_time */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/statements/get_run_time.js");
32637
32719
  const update_database_1 = __webpack_require__(/*! ./statements/update_database */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/statements/update_database.js");
32638
32720
  const add_1 = __webpack_require__(/*! ./statements/add */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/statements/add.js");
32721
+ const editor_call_1 = __webpack_require__(/*! ./statements/editor_call */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/statements/editor_call.js");
32639
32722
  const subtract_1 = __webpack_require__(/*! ./statements/subtract */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/statements/subtract.js");
32640
32723
  const add_corresponding_1 = __webpack_require__(/*! ./statements/add_corresponding */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/statements/add_corresponding.js");
32641
32724
  const subtract_corresponding_1 = __webpack_require__(/*! ./statements/subtract_corresponding */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/statements/subtract_corresponding.js");
@@ -32811,6 +32894,7 @@ if (Object.keys(map).length === 0) {
32811
32894
  addToMap(new translate_1.Translate());
32812
32895
  addToMap(new modify_internal_1.ModifyInternal());
32813
32896
  addToMap(new read_textpool_1.ReadTextpool());
32897
+ addToMap(new editor_call_1.EditorCall());
32814
32898
  }
32815
32899
  // -----------------------------------
32816
32900
  class SyntaxLogic {
@@ -40177,8 +40261,8 @@ exports.MemoryFile = MemoryFile;
40177
40261
  "use strict";
40178
40262
 
40179
40263
  Object.defineProperty(exports, "__esModule", ({ value: true }));
40180
- exports.Visibility = exports.Info = exports.Rename = exports.PrettyPrinter = exports.Position = exports.CurrentScope = exports.ABAPFile = exports.RulesRunner = exports.SpaghettiScope = exports.SyntaxLogic = exports.ABAPObject = exports.Tokens = exports.ExpressionsCDS = exports.CDSParser = exports.LanguageServerTypes = exports.DDLParser = exports.applyEditList = exports.applyEditSingle = exports.SpaghettiScopeNode = exports.AbstractFile = exports.Token = exports.ScopeType = exports.BasicTypes = exports.TypedIdentifier = exports.AbstractType = exports.VirtualPosition = exports.Comment = exports.Unknown = exports.Empty = exports.Identifier = exports.Nodes = exports.Types = exports.Expressions = exports.Statements = exports.Structures = exports.SkipLogic = exports.Objects = exports.ArtifactsRules = exports.ArtifactsObjects = exports.ArtifactsABAP = exports.BuiltIn = exports.MethodLengthStats = exports.LanguageServer = exports.Registry = exports.CyclomaticComplexityStats = exports.ReferenceType = exports.Version = exports.Config = exports.Issue = exports.MemoryFile = void 0;
40181
- exports.RuleTag = exports.Severity = void 0;
40264
+ exports.Info = exports.Diagnostics = exports.Rename = exports.PrettyPrinter = exports.Position = exports.CurrentScope = exports.ABAPFile = exports.RulesRunner = exports.SpaghettiScope = exports.SyntaxLogic = exports.ABAPObject = exports.Tokens = exports.ExpressionsCDS = exports.CDSParser = exports.LanguageServerTypes = exports.DDLParser = exports.applyEditList = exports.applyEditSingle = exports.SpaghettiScopeNode = exports.AbstractFile = exports.Token = exports.ScopeType = exports.BasicTypes = exports.TypedIdentifier = exports.AbstractType = exports.VirtualPosition = exports.Comment = exports.Unknown = exports.Empty = exports.Identifier = exports.Nodes = exports.Types = exports.Expressions = exports.Statements = exports.Structures = exports.SkipLogic = exports.Objects = exports.ArtifactsRules = exports.ArtifactsObjects = exports.ArtifactsABAP = exports.BuiltIn = exports.MethodLengthStats = exports.LanguageServer = exports.Registry = exports.CyclomaticComplexityStats = exports.ReferenceType = exports.Version = exports.Config = exports.Issue = exports.MemoryFile = void 0;
40265
+ exports.LSPEdit = exports.RuleTag = exports.Severity = exports.Visibility = void 0;
40182
40266
  const issue_1 = __webpack_require__(/*! ./issue */ "./node_modules/@abaplint/core/build/src/issue.js");
40183
40267
  Object.defineProperty(exports, "Issue", ({ enumerable: true, get: function () { return issue_1.Issue; } }));
40184
40268
  const config_1 = __webpack_require__(/*! ./config */ "./node_modules/@abaplint/core/build/src/config.js");
@@ -40279,6 +40363,10 @@ const cyclomatic_complexity_stats_1 = __webpack_require__(/*! ./utils/cyclomatic
40279
40363
  Object.defineProperty(exports, "CyclomaticComplexityStats", ({ enumerable: true, get: function () { return cyclomatic_complexity_stats_1.CyclomaticComplexityStats; } }));
40280
40364
  const skip_logic_1 = __webpack_require__(/*! ./skip_logic */ "./node_modules/@abaplint/core/build/src/skip_logic.js");
40281
40365
  Object.defineProperty(exports, "SkipLogic", ({ enumerable: true, get: function () { return skip_logic_1.SkipLogic; } }));
40366
+ const diagnostics_1 = __webpack_require__(/*! ./lsp/diagnostics */ "./node_modules/@abaplint/core/build/src/lsp/diagnostics.js");
40367
+ Object.defineProperty(exports, "Diagnostics", ({ enumerable: true, get: function () { return diagnostics_1.Diagnostics; } }));
40368
+ const _edit_1 = __webpack_require__(/*! ./lsp/_edit */ "./node_modules/@abaplint/core/build/src/lsp/_edit.js");
40369
+ Object.defineProperty(exports, "LSPEdit", ({ enumerable: true, get: function () { return _edit_1.LSPEdit; } }));
40282
40370
  //# sourceMappingURL=index.js.map
40283
40371
 
40284
40372
  /***/ }),
@@ -40311,8 +40399,8 @@ class Issue {
40311
40399
  severity,
40312
40400
  });
40313
40401
  }
40314
- static atStatement(file, statement, message, key, severity, fix) {
40315
- return this.atRange(file, statement.getStart(), statement.getEnd(), message, key, severity, fix);
40402
+ static atStatement(file, statement, message, key, severity, fix, alternativeFixes) {
40403
+ return this.atRange(file, statement.getStart(), statement.getEnd(), message, key, severity, fix, alternativeFixes);
40316
40404
  }
40317
40405
  static atPosition(file, start, message, key, severity, fix) {
40318
40406
  const row = start.getRow();
@@ -40324,7 +40412,7 @@ class Issue {
40324
40412
  key,
40325
40413
  start,
40326
40414
  end,
40327
- fix,
40415
+ defaultFix: fix,
40328
40416
  severity,
40329
40417
  });
40330
40418
  }
@@ -40338,11 +40426,11 @@ class Issue {
40338
40426
  key,
40339
40427
  start,
40340
40428
  end,
40341
- fix,
40429
+ defaultFix: fix,
40342
40430
  severity,
40343
40431
  });
40344
40432
  }
40345
- static atRange(file, start, end, message, key, severity, fix) {
40433
+ static atRange(file, start, end, message, key, severity, fix, alternativeFixes) {
40346
40434
  severity = severity !== null && severity !== void 0 ? severity : severity_1.Severity.Error;
40347
40435
  return new Issue({
40348
40436
  filename: file.getFilename(),
@@ -40350,8 +40438,9 @@ class Issue {
40350
40438
  key,
40351
40439
  start,
40352
40440
  end,
40353
- fix,
40441
+ defaultFix: fix,
40354
40442
  severity,
40443
+ alternativeFixes,
40355
40444
  });
40356
40445
  }
40357
40446
  static atToken(file, token, message, key, severity, fix) {
@@ -40363,7 +40452,7 @@ class Issue {
40363
40452
  start: token.getStart(),
40364
40453
  end: token.getEnd(),
40365
40454
  severity,
40366
- fix,
40455
+ defaultFix: fix,
40367
40456
  });
40368
40457
  }
40369
40458
  static atIdentifier(identifier, message, key, severity, fix) {
@@ -40375,14 +40464,14 @@ class Issue {
40375
40464
  start: identifier.getStart(),
40376
40465
  end: identifier.getEnd(),
40377
40466
  severity,
40378
- fix,
40467
+ defaultFix: fix,
40379
40468
  });
40380
40469
  }
40381
40470
  constructor(data) {
40382
40471
  this.data = data;
40383
40472
  if (this.data.start instanceof virtual_position_1.VirtualPosition) {
40384
40473
  // no quick fixes inside macros
40385
- this.data.fix = undefined;
40474
+ this.data.defaultFix = undefined;
40386
40475
  }
40387
40476
  if (this.data.start.getCol() < 1) {
40388
40477
  throw new Error("issue, start col < 1");
@@ -40409,8 +40498,11 @@ class Issue {
40409
40498
  getFilename() {
40410
40499
  return this.data.filename;
40411
40500
  }
40412
- getFix() {
40413
- return this.data.fix;
40501
+ getDefaultFix() {
40502
+ return this.data.defaultFix;
40503
+ }
40504
+ getAlternativeFixes() {
40505
+ return this.data.alternativeFixes;
40414
40506
  }
40415
40507
  getSeverity() {
40416
40508
  return this.data.severity;
@@ -40445,22 +40537,6 @@ class LSPEdit {
40445
40537
  }
40446
40538
  return workspace;
40447
40539
  }
40448
- /*
40449
- public static mapEditsDocument(edit: IEdit): LServer.WorkspaceEdit {
40450
- const workspace: LServer.WorkspaceEdit = {documentChanges: []};
40451
- for (const filename in edit) {
40452
- const doc: LServer.VersionedTextDocumentIdentifier = {uri: filename, version: 1};
40453
-
40454
- const e = LServer.TextDocumentEdit.create(doc, this.mapText(edit[filename]));
40455
- workspace.documentChanges?.push(e);
40456
- }
40457
- // @ts-ignore
40458
- console.dir(workspace.documentChanges![0].edits[0]);
40459
- // @ts-ignore
40460
- console.dir(workspace.documentChanges![0].edits[1]);
40461
- return workspace;
40462
- }
40463
- */
40464
40540
  static mapEdit(edit) {
40465
40541
  const workspace = { changes: {} };
40466
40542
  for (const filename in edit) {
@@ -40963,27 +41039,37 @@ class CodeActions {
40963
41039
  const shown = new Set();
40964
41040
  const ret = [];
40965
41041
  for (const i of issues) {
40966
- const fix = i.getFix();
40967
- if (fix === undefined) {
40968
- continue;
40969
- }
40970
- if (totals[i.getKey()] === undefined) {
40971
- totals[i.getKey()] = 1;
40972
- }
40973
- else {
40974
- totals[i.getKey()]++;
41042
+ const fix = i.getDefaultFix();
41043
+ if (fix !== undefined) {
41044
+ if (totals[i.getKey()] === undefined) {
41045
+ totals[i.getKey()] = 1;
41046
+ }
41047
+ else {
41048
+ totals[i.getKey()]++;
41049
+ }
41050
+ if (this.inRange(i, params.range) === true) {
41051
+ ret.push({
41052
+ title: "Apply fix, " + i.getKey(),
41053
+ kind: LServer.CodeActionKind.QuickFix,
41054
+ diagnostics: [diagnostics_1.Diagnostics.mapDiagnostic(i)],
41055
+ isPreferred: true,
41056
+ edit: _edit_1.LSPEdit.mapEdit(fix),
41057
+ });
41058
+ shown.add(i.getKey());
41059
+ }
40975
41060
  }
40976
- if (this.inRange(i, params.range) === false) {
40977
- continue;
41061
+ for (const alternative of i.getAlternativeFixes() || []) {
41062
+ if (this.inRange(i, params.range) === true) {
41063
+ ret.push({
41064
+ title: alternative.description,
41065
+ kind: LServer.CodeActionKind.QuickFix,
41066
+ diagnostics: [diagnostics_1.Diagnostics.mapDiagnostic(i)],
41067
+ isPreferred: true,
41068
+ edit: _edit_1.LSPEdit.mapEdit(alternative.edit),
41069
+ });
41070
+ shown.add(i.getKey());
41071
+ }
40978
41072
  }
40979
- ret.push({
40980
- title: "Apply fix, " + i.getKey(),
40981
- kind: LServer.CodeActionKind.QuickFix,
40982
- diagnostics: [diagnostics_1.Diagnostics.mapDiagnostic(i)],
40983
- isPreferred: true,
40984
- edit: _edit_1.LSPEdit.mapEdit(fix),
40985
- });
40986
- shown.add(i.getKey());
40987
41073
  }
40988
41074
  for (const s of shown) {
40989
41075
  if (totals[s] > 1) {
@@ -40998,7 +41084,7 @@ class CodeActions {
40998
41084
  const diagnostics = [];
40999
41085
  const fixes = [];
41000
41086
  for (const i of issues) {
41001
- const fix = i.getFix();
41087
+ const fix = i.getDefaultFix();
41002
41088
  if (fix === undefined) {
41003
41089
  continue;
41004
41090
  }
@@ -44793,15 +44879,42 @@ class EnhancementImplementation extends _abstract_object_1.AbstractObject {
44793
44879
  getType() {
44794
44880
  return "ENHO";
44795
44881
  }
44882
+ setDirty() {
44883
+ this.parsedXML = undefined;
44884
+ super.setDirty();
44885
+ }
44796
44886
  getAllowedNaming() {
44797
44887
  return {
44798
44888
  maxLength: 30,
44799
44889
  allowNamespace: true,
44800
44890
  };
44801
44891
  }
44892
+ getClassName() {
44893
+ var _a;
44894
+ this.parse();
44895
+ return (_a = this.parsedXML) === null || _a === void 0 ? void 0 : _a.className;
44896
+ }
44802
44897
  getDescription() {
44803
- // todo
44804
- return undefined;
44898
+ var _a;
44899
+ this.parse();
44900
+ return (_a = this.parsedXML) === null || _a === void 0 ? void 0 : _a.description;
44901
+ }
44902
+ parse() {
44903
+ if (this.parsedXML) {
44904
+ return { updated: false, runtime: 0 };
44905
+ }
44906
+ const start = Date.now();
44907
+ this.parsedXML = {};
44908
+ const parsed = super.parseRaw2();
44909
+ if (parsed === undefined
44910
+ || parsed.abapGit === undefined
44911
+ || parsed.abapGit["asx:abap"]["asx:values"] === undefined) {
44912
+ return { updated: false, runtime: 0 };
44913
+ }
44914
+ this.parsedXML.className = parsed.abapGit["asx:abap"]["asx:values"].CLASS;
44915
+ this.parsedXML.description = parsed.abapGit["asx:abap"]["asx:values"].SHORTTEXT;
44916
+ const end = Date.now();
44917
+ return { updated: true, runtime: end - start };
44805
44918
  }
44806
44919
  }
44807
44920
  exports.EnhancementImplementation = EnhancementImplementation;
@@ -44941,6 +45054,10 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
44941
45054
  exports.ExtensionIndex = void 0;
44942
45055
  const _abstract_object_1 = __webpack_require__(/*! ./_abstract_object */ "./node_modules/@abaplint/core/build/src/objects/_abstract_object.js");
44943
45056
  class ExtensionIndex extends _abstract_object_1.AbstractObject {
45057
+ constructor() {
45058
+ super(...arguments);
45059
+ this.parsedXML = undefined;
45060
+ }
44944
45061
  getType() {
44945
45062
  return "XINX";
44946
45063
  }
@@ -44950,9 +45067,38 @@ class ExtensionIndex extends _abstract_object_1.AbstractObject {
44950
45067
  allowNamespace: true,
44951
45068
  };
44952
45069
  }
45070
+ setDirty() {
45071
+ this.parsedXML = undefined;
45072
+ super.setDirty();
45073
+ }
44953
45074
  getDescription() {
44954
- // todo
44955
- return undefined;
45075
+ var _a;
45076
+ this.parse();
45077
+ return (_a = this.parsedXML) === null || _a === void 0 ? void 0 : _a.ddtext;
45078
+ }
45079
+ getTableName() {
45080
+ var _a;
45081
+ this.parse();
45082
+ return (_a = this.parsedXML) === null || _a === void 0 ? void 0 : _a.sqltab;
45083
+ }
45084
+ parse() {
45085
+ var _a, _b, _c, _d, _e;
45086
+ if (this.parsedXML !== undefined) {
45087
+ return { updated: false, runtime: 0 };
45088
+ }
45089
+ const start = Date.now();
45090
+ this.parsedXML = {};
45091
+ const parsed = super.parseRaw2();
45092
+ if (parsed === undefined) {
45093
+ return { updated: false, runtime: 0 };
45094
+ }
45095
+ const xinx = (_c = (_b = (_a = parsed.abapGit) === null || _a === void 0 ? void 0 : _a["asx:abap"]) === null || _b === void 0 ? void 0 : _b["asx:values"]) === null || _c === void 0 ? void 0 : _c.XINX;
45096
+ this.parsedXML = {
45097
+ sqltab: (_d = xinx === null || xinx === void 0 ? void 0 : xinx.DD12V) === null || _d === void 0 ? void 0 : _d.SQLTAB,
45098
+ ddtext: (_e = xinx === null || xinx === void 0 ? void 0 : xinx.DD12V) === null || _e === void 0 ? void 0 : _e.DDTEXT,
45099
+ };
45100
+ const end = Date.now();
45101
+ return { updated: true, runtime: end - start };
44956
45102
  }
44957
45103
  }
44958
45104
  exports.ExtensionIndex = ExtensionIndex;
@@ -48910,12 +49056,14 @@ class Table extends _abstract_object_1.AbstractObject {
48910
49056
  }
48911
49057
  getAllowedNaming() {
48912
49058
  let length = 30;
49059
+ const regex = /^((\/[A-Z_\d]{3,8}\/)|[a-zA-Z0-9]{3})\w+$/;
48913
49060
  if (this.getTableCategory() === TableCategory.Transparent) {
48914
49061
  length = 16;
48915
49062
  }
48916
49063
  return {
48917
49064
  maxLength: length,
48918
49065
  allowNamespace: true,
49066
+ customRegex: regex,
48919
49067
  };
48920
49068
  }
48921
49069
  setDirty() {
@@ -49427,15 +49575,43 @@ class Transaction extends _abstract_object_1.AbstractObject {
49427
49575
  getType() {
49428
49576
  return "TRAN";
49429
49577
  }
49578
+ setDirty() {
49579
+ this.parsedXML = undefined;
49580
+ super.setDirty();
49581
+ }
49430
49582
  getAllowedNaming() {
49431
49583
  return {
49432
49584
  maxLength: 20,
49433
49585
  allowNamespace: true,
49434
49586
  };
49435
49587
  }
49588
+ getProgramName() {
49589
+ var _a;
49590
+ this.parse();
49591
+ return (_a = this.parsedXML) === null || _a === void 0 ? void 0 : _a.programName;
49592
+ }
49436
49593
  getDescription() {
49437
- // todo
49438
- return undefined;
49594
+ var _a;
49595
+ this.parse();
49596
+ return (_a = this.parsedXML) === null || _a === void 0 ? void 0 : _a.description;
49597
+ }
49598
+ parse() {
49599
+ var _a, _b;
49600
+ if (this.parsedXML) {
49601
+ return { updated: false, runtime: 0 };
49602
+ }
49603
+ const start = Date.now();
49604
+ this.parsedXML = {};
49605
+ const parsed = super.parseRaw2();
49606
+ if (parsed === undefined
49607
+ || parsed.abapGit === undefined
49608
+ || parsed.abapGit["asx:abap"]["asx:values"] === undefined) {
49609
+ return { updated: false, runtime: 0 };
49610
+ }
49611
+ this.parsedXML.description = (_a = parsed.abapGit["asx:abap"]["asx:values"].TSTCT) === null || _a === void 0 ? void 0 : _a.TTEXT;
49612
+ this.parsedXML.programName = (_b = parsed.abapGit["asx:abap"]["asx:values"].TSTC) === null || _b === void 0 ? void 0 : _b.PGMNA;
49613
+ const end = Date.now();
49614
+ return { updated: true, runtime: end - start };
49439
49615
  }
49440
49616
  }
49441
49617
  exports.Transaction = Transaction;
@@ -49557,6 +49733,10 @@ const Types = __webpack_require__(/*! ../abap/types/basic */ "./node_modules/@ab
49557
49733
  const _abstract_object_1 = __webpack_require__(/*! ./_abstract_object */ "./node_modules/@abaplint/core/build/src/objects/_abstract_object.js");
49558
49734
  const xml_utils_1 = __webpack_require__(/*! ../xml_utils */ "./node_modules/@abaplint/core/build/src/xml_utils.js");
49559
49735
  const ddic_1 = __webpack_require__(/*! ../ddic */ "./node_modules/@abaplint/core/build/src/ddic.js");
49736
+ var ViewClass;
49737
+ (function (ViewClass) {
49738
+ ViewClass["ExternalView"] = "X";
49739
+ })(ViewClass || (ViewClass = {}));
49560
49740
  class View extends _abstract_object_1.AbstractObject {
49561
49741
  getType() {
49562
49742
  return "VIEW";
@@ -49600,6 +49780,16 @@ class View extends _abstract_object_1.AbstractObject {
49600
49780
  // ignore, this is a special case of old style .INCLUDE
49601
49781
  continue;
49602
49782
  }
49783
+ else if (this.parsedData.header.VIEWCLASS === ViewClass.ExternalView) {
49784
+ components.push({
49785
+ name: field.VIEWFIELD,
49786
+ type: new Types.VoidType("ExternalView")
49787
+ });
49788
+ continue;
49789
+ }
49790
+ else if (field.TABNAME === this.getName()) {
49791
+ throw new Error("Unexpected self reference in view " + this.getName() + ", " + field.FIELDNAME + " " + field.FIELDNAME);
49792
+ }
49603
49793
  const lookup = ddic.lookupTableOrView(field.TABNAME);
49604
49794
  let found = lookup.type;
49605
49795
  if (lookup.object) {
@@ -49635,13 +49825,23 @@ class View extends _abstract_object_1.AbstractObject {
49635
49825
  }
49636
49826
  ///////////////
49637
49827
  parseXML() {
49638
- var _a, _b;
49639
- this.parsedData = { fields: [], join: [] };
49828
+ var _a, _b, _c;
49829
+ this.parsedData = {
49830
+ header: {
49831
+ VIEWCLASS: "",
49832
+ },
49833
+ fields: [],
49834
+ join: [],
49835
+ };
49640
49836
  const parsed = super.parseRaw2();
49641
49837
  if (parsed === undefined || parsed.abapGit === undefined) {
49642
49838
  return;
49643
49839
  }
49644
- const fields = (_a = parsed.abapGit["asx:abap"]["asx:values"]) === null || _a === void 0 ? void 0 : _a.DD27P_TABLE;
49840
+ const header = (_a = parsed.abapGit["asx:abap"]["asx:values"]) === null || _a === void 0 ? void 0 : _a.DD25V;
49841
+ this.parsedData.header = {
49842
+ VIEWCLASS: (header === null || header === void 0 ? void 0 : header.VIEWCLASS) || "",
49843
+ };
49844
+ const fields = (_b = parsed.abapGit["asx:abap"]["asx:values"]) === null || _b === void 0 ? void 0 : _b.DD27P_TABLE;
49645
49845
  for (const field of (0, xml_utils_1.xmlToArray)(fields === null || fields === void 0 ? void 0 : fields.DD27P)) {
49646
49846
  this.parsedData.fields.push({
49647
49847
  VIEWFIELD: field.VIEWFIELD,
@@ -49649,7 +49849,7 @@ class View extends _abstract_object_1.AbstractObject {
49649
49849
  FIELDNAME: field.FIELDNAME,
49650
49850
  });
49651
49851
  }
49652
- const join = (_b = parsed.abapGit["asx:abap"]["asx:values"]) === null || _b === void 0 ? void 0 : _b.DD28J_TABLE;
49852
+ const join = (_c = parsed.abapGit["asx:abap"]["asx:values"]) === null || _c === void 0 ? void 0 : _c.DD28J_TABLE;
49653
49853
  for (const j of (0, xml_utils_1.xmlToArray)(join === null || join === void 0 ? void 0 : join.DD28J)) {
49654
49854
  this.parsedData.join.push({
49655
49855
  LTAB: j.LTAB,
@@ -50383,7 +50583,7 @@ class Registry {
50383
50583
  }
50384
50584
  static abaplintVersion() {
50385
50585
  // magic, see build script "version.sh"
50386
- return "2.106.5";
50586
+ return "2.108.12";
50387
50587
  }
50388
50588
  getDDICReferences() {
50389
50589
  return this.ddicReferences;
@@ -50705,6 +50905,8 @@ https://help.sap.com/doc/abapdocu_750_index_htm/7.50/en-US/abencharacter_set_gui
50705
50905
 
50706
50906
  Checkes files with extensions ".abap" and ".asddls"`,
50707
50907
  tags: [_irule_1.RuleTag.SingleFile],
50908
+ badExample: `WRITE '뽑'.`,
50909
+ goodExample: `WRITE cl_abap_conv_in_ce=>uccp( 'BF51' ).`,
50708
50910
  };
50709
50911
  }
50710
50912
  initialize(_reg) {
@@ -51401,6 +51603,273 @@ exports.AlignParameters = AlignParameters;
51401
51603
 
51402
51604
  /***/ }),
51403
51605
 
51606
+ /***/ "./node_modules/@abaplint/core/build/src/rules/align_pseudo_comments.js":
51607
+ /*!******************************************************************************!*\
51608
+ !*** ./node_modules/@abaplint/core/build/src/rules/align_pseudo_comments.js ***!
51609
+ \******************************************************************************/
51610
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
51611
+
51612
+ "use strict";
51613
+
51614
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
51615
+ exports.AlignPseudoComments = exports.AlignPseudoCommentsConf = void 0;
51616
+ const _abap_rule_1 = __webpack_require__(/*! ./_abap_rule */ "./node_modules/@abaplint/core/build/src/rules/_abap_rule.js");
51617
+ const _basic_rule_config_1 = __webpack_require__(/*! ./_basic_rule_config */ "./node_modules/@abaplint/core/build/src/rules/_basic_rule_config.js");
51618
+ const _irule_1 = __webpack_require__(/*! ./_irule */ "./node_modules/@abaplint/core/build/src/rules/_irule.js");
51619
+ const issue_1 = __webpack_require__(/*! ../issue */ "./node_modules/@abaplint/core/build/src/issue.js");
51620
+ const _statement_1 = __webpack_require__(/*! ../abap/2_statements/statements/_statement */ "./node_modules/@abaplint/core/build/src/abap/2_statements/statements/_statement.js");
51621
+ const position_1 = __webpack_require__(/*! ../position */ "./node_modules/@abaplint/core/build/src/position.js");
51622
+ const edit_helper_1 = __webpack_require__(/*! ../edit_helper */ "./node_modules/@abaplint/core/build/src/edit_helper.js");
51623
+ class AlignPseudoCommentsConf extends _basic_rule_config_1.BasicRuleConfig {
51624
+ }
51625
+ exports.AlignPseudoCommentsConf = AlignPseudoCommentsConf;
51626
+ class AlignPseudoComments extends _abap_rule_1.ABAPRule {
51627
+ constructor() {
51628
+ super(...arguments);
51629
+ this.conf = new AlignPseudoCommentsConf();
51630
+ }
51631
+ getMetadata() {
51632
+ return {
51633
+ key: "align_pseudo_comments",
51634
+ title: "Align pseudo comments",
51635
+ shortDescription: `Align code inspector pseudo comments in statements`,
51636
+ tags: [_irule_1.RuleTag.SingleFile, _irule_1.RuleTag.Whitespace, _irule_1.RuleTag.Quickfix],
51637
+ badExample: `WRITE 'sdf'. "#EC sdf`,
51638
+ goodExample: `WRITE 'sdf'. "#EC sdf`,
51639
+ };
51640
+ }
51641
+ getConfig() {
51642
+ return this.conf;
51643
+ }
51644
+ setConfig(conf) {
51645
+ this.conf = conf;
51646
+ }
51647
+ runParsed(file) {
51648
+ const issues = [];
51649
+ let previousEnd = undefined;
51650
+ for (const statement of file.getStatements()) {
51651
+ if (!(statement.get() instanceof _statement_1.Comment)) {
51652
+ previousEnd = statement.getLastToken().getEnd();
51653
+ continue;
51654
+ }
51655
+ const commentLength = statement.concatTokens().length;
51656
+ const firstCommentToken = statement.getFirstToken();
51657
+ if (firstCommentToken.getStr().startsWith(`"#`) === false) {
51658
+ continue;
51659
+ }
51660
+ else if (previousEnd === undefined) {
51661
+ continue;
51662
+ }
51663
+ let expectedColumn = 61;
51664
+ if (commentLength > 10) {
51665
+ expectedColumn = 72 - commentLength;
51666
+ }
51667
+ const col = firstCommentToken.getStart().getCol();
51668
+ if (previousEnd.getCol() < expectedColumn && col !== expectedColumn) {
51669
+ let fix = undefined;
51670
+ if (col < expectedColumn) {
51671
+ fix = edit_helper_1.EditHelper.insertAt(file, firstCommentToken.getStart(), " ".repeat(expectedColumn - col));
51672
+ }
51673
+ else {
51674
+ const from = new position_1.Position(firstCommentToken.getStart().getRow(), expectedColumn);
51675
+ fix = edit_helper_1.EditHelper.deleteRange(file, from, firstCommentToken.getStart());
51676
+ }
51677
+ const message = "Align pseudo comment to column " + expectedColumn;
51678
+ issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity, fix));
51679
+ }
51680
+ }
51681
+ return issues;
51682
+ }
51683
+ }
51684
+ exports.AlignPseudoComments = AlignPseudoComments;
51685
+ //# sourceMappingURL=align_pseudo_comments.js.map
51686
+
51687
+ /***/ }),
51688
+
51689
+ /***/ "./node_modules/@abaplint/core/build/src/rules/align_type_expressions.js":
51690
+ /*!*******************************************************************************!*\
51691
+ !*** ./node_modules/@abaplint/core/build/src/rules/align_type_expressions.js ***!
51692
+ \*******************************************************************************/
51693
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
51694
+
51695
+ "use strict";
51696
+
51697
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
51698
+ exports.AlignTypeExpressions = exports.AlignTypeExpressionsConf = void 0;
51699
+ const _abap_rule_1 = __webpack_require__(/*! ./_abap_rule */ "./node_modules/@abaplint/core/build/src/rules/_abap_rule.js");
51700
+ const _basic_rule_config_1 = __webpack_require__(/*! ./_basic_rule_config */ "./node_modules/@abaplint/core/build/src/rules/_basic_rule_config.js");
51701
+ const objects_1 = __webpack_require__(/*! ../objects */ "./node_modules/@abaplint/core/build/src/objects/index.js");
51702
+ const ddic_1 = __webpack_require__(/*! ../ddic */ "./node_modules/@abaplint/core/build/src/ddic.js");
51703
+ const _irule_1 = __webpack_require__(/*! ./_irule */ "./node_modules/@abaplint/core/build/src/rules/_irule.js");
51704
+ const issue_1 = __webpack_require__(/*! ../issue */ "./node_modules/@abaplint/core/build/src/issue.js");
51705
+ const position_1 = __webpack_require__(/*! ../position */ "./node_modules/@abaplint/core/build/src/position.js");
51706
+ const Expressions = __webpack_require__(/*! ../abap/2_statements/expressions */ "./node_modules/@abaplint/core/build/src/abap/2_statements/expressions/index.js");
51707
+ const Statements = __webpack_require__(/*! ../abap/2_statements/statements */ "./node_modules/@abaplint/core/build/src/abap/2_statements/statements/index.js");
51708
+ const Structures = __webpack_require__(/*! ../abap/3_structures/structures */ "./node_modules/@abaplint/core/build/src/abap/3_structures/structures/index.js");
51709
+ const edit_helper_1 = __webpack_require__(/*! ../edit_helper */ "./node_modules/@abaplint/core/build/src/edit_helper.js");
51710
+ class AlignTypeExpressionsConf extends _basic_rule_config_1.BasicRuleConfig {
51711
+ constructor() {
51712
+ super(...arguments);
51713
+ /** Ignore global exception classes */
51714
+ this.ignoreExceptions = true;
51715
+ }
51716
+ }
51717
+ exports.AlignTypeExpressionsConf = AlignTypeExpressionsConf;
51718
+ class AlignTypeExpressions extends _abap_rule_1.ABAPRule {
51719
+ constructor() {
51720
+ super(...arguments);
51721
+ this.conf = new AlignTypeExpressionsConf();
51722
+ }
51723
+ getMetadata() {
51724
+ return {
51725
+ key: "align_type_expressions",
51726
+ title: "Align TYPE expressions",
51727
+ shortDescription: `Align TYPE expressions in statements`,
51728
+ extendedInformation: `
51729
+ Currently works for METHODS + BEGIN OF
51730
+
51731
+ If BEGIN OF has an INCLUDE TYPE its ignored
51732
+
51733
+ Also note that clean ABAP does not recommend aligning TYPE clauses:
51734
+ https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#dont-align-type-clauses`,
51735
+ tags: [_irule_1.RuleTag.SingleFile, _irule_1.RuleTag.Whitespace, _irule_1.RuleTag.Quickfix],
51736
+ badExample: `
51737
+ TYPES: BEGIN OF foo,
51738
+ bar TYPE i,
51739
+ foobar TYPE i,
51740
+ END OF foo.
51741
+
51742
+ INTERFACE lif.
51743
+ METHODS bar
51744
+ IMPORTING
51745
+ foo TYPE i
51746
+ foobar TYPE i.
51747
+ ENDINTERFACE.`,
51748
+ goodExample: `
51749
+ TYPES: BEGIN OF foo,
51750
+ bar TYPE i,
51751
+ foobar TYPE i,
51752
+ END OF foo.
51753
+
51754
+ INTERFACE lif.
51755
+ METHODS bar
51756
+ IMPORTING
51757
+ foo TYPE i
51758
+ foobar TYPE i.
51759
+ ENDINTERFACE.`,
51760
+ };
51761
+ }
51762
+ getConfig() {
51763
+ return this.conf;
51764
+ }
51765
+ setConfig(conf) {
51766
+ this.conf = conf;
51767
+ }
51768
+ runParsed(file, obj) {
51769
+ const issues = [];
51770
+ const stru = file.getStructure();
51771
+ if (stru === undefined) {
51772
+ return issues; // parser error
51773
+ }
51774
+ const ddic = new ddic_1.DDIC(this.reg);
51775
+ if (obj instanceof objects_1.Class) {
51776
+ const definition = obj.getClassDefinition();
51777
+ if (definition === undefined) {
51778
+ return [];
51779
+ }
51780
+ else if (this.conf.ignoreExceptions && ddic.isException(definition, obj)) {
51781
+ return [];
51782
+ }
51783
+ }
51784
+ issues.push(...this.checkTypes(stru, file));
51785
+ issues.push(...this.checkMethods(stru, file));
51786
+ return issues;
51787
+ }
51788
+ check(fields, column, file) {
51789
+ const issues = [];
51790
+ const rows = new Set();
51791
+ for (const f of fields) {
51792
+ const row = f.after.getRow();
51793
+ if (rows.has(row)) {
51794
+ return [];
51795
+ }
51796
+ rows.add(row);
51797
+ }
51798
+ for (const f of fields) {
51799
+ if (f.after.getCol() === column) {
51800
+ continue;
51801
+ }
51802
+ let fix = undefined;
51803
+ if (f.after.getCol() < column) {
51804
+ fix = edit_helper_1.EditHelper.insertAt(file, f.after, " ".repeat(column - f.after.getCol()));
51805
+ }
51806
+ else {
51807
+ fix = edit_helper_1.EditHelper.deleteRange(file, new position_1.Position(f.after.getRow(), column), f.after);
51808
+ }
51809
+ const message = `Align TYPE expressions to column ${column}`;
51810
+ const issue = issue_1.Issue.atPosition(file, f.after, message, this.getMetadata().key, this.conf.severity, fix);
51811
+ issues.push(issue);
51812
+ }
51813
+ return issues;
51814
+ }
51815
+ checkMethods(stru, file) {
51816
+ const issues = [];
51817
+ const methods = stru.findAllStatements(Statements.MethodDef);
51818
+ for (const m of methods) {
51819
+ const fields = [];
51820
+ const params = m.findAllExpressions(Expressions.MethodParam);
51821
+ let column = 0;
51822
+ for (const p of params) {
51823
+ const children = p.getChildren();
51824
+ const name = children[children.length - 2];
51825
+ fields.push({
51826
+ nameEnd: name.getLastToken().getEnd(),
51827
+ after: p.findFirstExpression(Expressions.TypeParam).getFirstToken().getStart()
51828
+ });
51829
+ column = Math.max(column, name.getFirstToken().getEnd().getCol() + 1);
51830
+ }
51831
+ const ret = m.findFirstExpression(Expressions.MethodDefReturning);
51832
+ if (ret) {
51833
+ const children = ret.getChildren();
51834
+ const name = children[children.length - 2];
51835
+ fields.push({
51836
+ nameEnd: name.getLastToken().getEnd(),
51837
+ after: ret.findFirstExpression(Expressions.TypeParam).getFirstToken().getStart()
51838
+ });
51839
+ column = Math.max(column, name.getLastToken().getEnd().getCol() + 1);
51840
+ }
51841
+ issues.push(...this.check(fields, column, file));
51842
+ }
51843
+ return issues;
51844
+ }
51845
+ checkTypes(stru, file) {
51846
+ const issues = [];
51847
+ const types = stru.findAllStructuresRecursive(Structures.Types);
51848
+ for (const t of types) {
51849
+ if (t.findDirectStatement(Statements.IncludeType)) {
51850
+ continue;
51851
+ }
51852
+ const fields = [];
51853
+ let column = 0;
51854
+ const st = t.findDirectStatements(Statements.Type);
51855
+ for (const s of st) {
51856
+ const name = s.getChildren()[1];
51857
+ fields.push({
51858
+ nameEnd: name.getLastToken().getEnd(),
51859
+ after: s.getChildren()[2].getFirstToken().getStart()
51860
+ });
51861
+ column = Math.max(column, name.getFirstToken().getEnd().getCol() + 1);
51862
+ }
51863
+ issues.push(...this.check(fields, column, file));
51864
+ }
51865
+ return issues;
51866
+ }
51867
+ }
51868
+ exports.AlignTypeExpressions = AlignTypeExpressions;
51869
+ //# sourceMappingURL=align_type_expressions.js.map
51870
+
51871
+ /***/ }),
51872
+
51404
51873
  /***/ "./node_modules/@abaplint/core/build/src/rules/allowed_object_naming.js":
51405
51874
  /*!******************************************************************************!*\
51406
51875
  !*** ./node_modules/@abaplint/core/build/src/rules/allowed_object_naming.js ***!
@@ -51932,7 +52401,8 @@ STATICS BEGIN OF bar.
51932
52401
  INCLUDE STRUCTURE syst.
51933
52402
  STATICS END OF bar.`,
51934
52403
  goodExample: `DATA BEGIN OF foo.
51935
- INCLUDE STRUCTURE dselc.
52404
+ DATA field TYPE i.
52405
+ INCLUDE STRUCTURE dselc.
51936
52406
  DATA END OF foo.`,
51937
52407
  };
51938
52408
  }
@@ -52413,7 +52883,7 @@ https://help.sap.com/doc/abapdocu_751_index_htm/7.51/en-US/abenchained_statement
52413
52883
  }
52414
52884
  let prevFix;
52415
52885
  if (previousRow === colon.getStart().getRow()) {
52416
- prevFix = (_a = issues.pop()) === null || _a === void 0 ? void 0 : _a.getFix();
52886
+ prevFix = (_a = issues.pop()) === null || _a === void 0 ? void 0 : _a.getDefaultFix();
52417
52887
  }
52418
52888
  const fix = this.getFix(file, statement, statementNode, prevFix);
52419
52889
  const message = "Chain mainly declarations";
@@ -52942,6 +53412,7 @@ const _basic_rule_config_1 = __webpack_require__(/*! ./_basic_rule_config */ "./
52942
53412
  const _abap_rule_1 = __webpack_require__(/*! ./_abap_rule */ "./node_modules/@abaplint/core/build/src/rules/_abap_rule.js");
52943
53413
  const _irule_1 = __webpack_require__(/*! ./_irule */ "./node_modules/@abaplint/core/build/src/rules/_irule.js");
52944
53414
  const _statement_1 = __webpack_require__(/*! ../abap/2_statements/statements/_statement */ "./node_modules/@abaplint/core/build/src/abap/2_statements/statements/_statement.js");
53415
+ const edit_helper_1 = __webpack_require__(/*! ../edit_helper */ "./node_modules/@abaplint/core/build/src/edit_helper.js");
52945
53416
  class CheckSubrcConf extends _basic_rule_config_1.BasicRuleConfig {
52946
53417
  constructor() {
52947
53418
  super(...arguments);
@@ -52977,7 +53448,7 @@ If sy-dbcnt is checked after database statements, it is considered okay.
52977
53448
  If IS ASSIGNED is checked after assigning, it is considered okay.
52978
53449
 
52979
53450
  FIND statement with MATCH COUNT is considered okay if subrc is not checked`,
52980
- tags: [_irule_1.RuleTag.SingleFile],
53451
+ tags: [_irule_1.RuleTag.SingleFile, _irule_1.RuleTag.Quickfix],
52981
53452
  pseudoComment: "EC CI_SUBRC",
52982
53453
  pragma: "##SUBRC_OK",
52983
53454
  };
@@ -52988,6 +53459,12 @@ FIND statement with MATCH COUNT is considered okay if subrc is not checked`,
52988
53459
  setConfig(conf) {
52989
53460
  this.conf = conf;
52990
53461
  }
53462
+ buildFix(file, statement) {
53463
+ return {
53464
+ description: "Add ##SUBRC_OK",
53465
+ edit: edit_helper_1.EditHelper.insertAt(file, statement.getLastToken().getStart(), " ##SUBRC_OK"),
53466
+ };
53467
+ }
52991
53468
  runParsed(file) {
52992
53469
  const issues = [];
52993
53470
  const statements = file.getStatements();
@@ -53002,11 +53479,13 @@ FIND statement with MATCH COUNT is considered okay if subrc is not checked`,
53002
53479
  if (config.openDataset === true
53003
53480
  && statement.get() instanceof Statements.OpenDataset
53004
53481
  && this.isChecked(i, statements) === false) {
53482
+ // it doesnt make sense to ignore the subrc for open dataset, so no quick fix
53005
53483
  issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity));
53006
53484
  }
53007
53485
  else if (config.authorityCheck === true
53008
53486
  && statement.get() instanceof Statements.AuthorityCheck
53009
53487
  && this.isChecked(i, statements) === false) {
53488
+ // it doesnt make sense to ignore the subrc for authority checks, so no quick fix
53010
53489
  issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity));
53011
53490
  }
53012
53491
  else if (config.selectSingle === true
@@ -53018,7 +53497,8 @@ FIND statement with MATCH COUNT is considered okay if subrc is not checked`,
53018
53497
  if (concat.startsWith("SELECT SINGLE @ABAP_TRUE FROM ")) {
53019
53498
  continue;
53020
53499
  }
53021
- issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity));
53500
+ const fix = this.buildFix(file, statement);
53501
+ issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity, undefined, [fix]));
53022
53502
  }
53023
53503
  else if (config.selectTable === true
53024
53504
  && statement.get() instanceof Statements.Select
@@ -53027,42 +53507,49 @@ FIND statement with MATCH COUNT is considered okay if subrc is not checked`,
53027
53507
  && statement.concatTokens().toUpperCase().startsWith("SELECT COUNT(*) ") === false
53028
53508
  && this.isChecked(i, statements) === false
53029
53509
  && this.checksDbcnt(i, statements) === false) {
53030
- issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity));
53510
+ const fix = this.buildFix(file, statement);
53511
+ issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity, undefined, [fix]));
53031
53512
  }
53032
53513
  else if (config.updateDatabase === true
53033
53514
  && statement.get() instanceof Statements.UpdateDatabase
53034
53515
  && this.isChecked(i, statements) === false
53035
53516
  && this.checksDbcnt(i, statements) === false) {
53036
- issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity));
53517
+ const fix = this.buildFix(file, statement);
53518
+ issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity, undefined, [fix]));
53037
53519
  }
53038
53520
  else if (config.insertDatabase === true
53039
53521
  && statement.get() instanceof Statements.InsertDatabase
53040
53522
  && this.isChecked(i, statements) === false
53041
53523
  && this.checksDbcnt(i, statements) === false) {
53042
- issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity));
53524
+ const fix = this.buildFix(file, statement);
53525
+ issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity, undefined, [fix]));
53043
53526
  }
53044
53527
  else if (config.modifyDatabase === true
53045
53528
  && statement.get() instanceof Statements.ModifyDatabase
53046
53529
  && this.isChecked(i, statements) === false
53047
53530
  && this.checksDbcnt(i, statements) === false) {
53048
- issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity));
53531
+ const fix = this.buildFix(file, statement);
53532
+ issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity, undefined, [fix]));
53049
53533
  }
53050
53534
  else if (config.readTable === true
53051
53535
  && statement.get() instanceof Statements.ReadTable
53052
53536
  && this.isChecked(i, statements) === false) {
53053
- issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity));
53537
+ const fix = this.buildFix(file, statement);
53538
+ issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity, undefined, [fix]));
53054
53539
  }
53055
53540
  else if (config.assign === true
53056
53541
  && statement.get() instanceof Statements.Assign
53057
53542
  && this.isSimpleAssign(statement) === false
53058
53543
  && this.isChecked(i, statements) === false) {
53059
- issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity));
53544
+ const fix = this.buildFix(file, statement);
53545
+ issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity, undefined, [fix]));
53060
53546
  }
53061
53547
  else if (config.find === true
53062
53548
  && statement.get() instanceof Statements.Find
53063
53549
  && this.isExemptedFind(statement) === false
53064
53550
  && this.isChecked(i, statements) === false) {
53065
- issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity));
53551
+ const fix = this.buildFix(file, statement);
53552
+ issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity, undefined, [fix]));
53066
53553
  }
53067
53554
  }
53068
53555
  return issues;
@@ -53787,6 +54274,7 @@ class CommentedCode extends _abap_rule_1.ABAPRule {
53787
54274
  extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#delete-code-instead-of-commenting-it
53788
54275
  https://docs.abapopenchecks.org/checks/14/`,
53789
54276
  tags: [_irule_1.RuleTag.Styleguide, _irule_1.RuleTag.Quickfix, _irule_1.RuleTag.SingleFile],
54277
+ badExample: `* WRITE 'hello world'.`,
53790
54278
  };
53791
54279
  }
53792
54280
  getMessage() {
@@ -54098,6 +54586,8 @@ class ContainsTab extends _abap_rule_1.ABAPRule {
54098
54586
  https://docs.abapopenchecks.org/checks/09/
54099
54587
  https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#indent-and-snap-to-tab`,
54100
54588
  tags: [_irule_1.RuleTag.Whitespace, _irule_1.RuleTag.Quickfix, _irule_1.RuleTag.Styleguide, _irule_1.RuleTag.SingleFile],
54589
+ badExample: `\tWRITE 'hello world'.`,
54590
+ goodExample: ` WRITE 'hello world'.`,
54101
54591
  };
54102
54592
  }
54103
54593
  getMessage() {
@@ -55567,6 +56057,10 @@ Make sure to test the downported code, it might not always be completely correct
55567
56057
  if (found) {
55568
56058
  return found;
55569
56059
  }
56060
+ found = this.downportMessageSource(high, lowFile, highSyntax);
56061
+ if (found) {
56062
+ return found;
56063
+ }
55570
56064
  found = this.downportMessage(high, lowFile, highSyntax);
55571
56065
  if (found) {
55572
56066
  return found;
@@ -55921,6 +56415,22 @@ ${indentation}${uniqueName} = ${source.concatTokens()}.\n${indentation}`);
55921
56415
  }
55922
56416
  return undefined;
55923
56417
  }
56418
+ downportMessageSource(high, lowFile, highSyntax) {
56419
+ if (!(high.get() instanceof Statements.Message)) {
56420
+ return undefined;
56421
+ }
56422
+ const source = high.findExpressionAfterToken("MESSAGE");
56423
+ if ((source === null || source === void 0 ? void 0 : source.get()) instanceof Expressions.Source) {
56424
+ const uniqueName = this.uniqueName(high.getFirstToken().getStart(), lowFile.getFilename(), highSyntax);
56425
+ const indentation = " ".repeat(high.getFirstToken().getStart().getCol() - 1);
56426
+ const firstToken = high.getFirstToken();
56427
+ const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, firstToken.getStart(), `DATA(${uniqueName}) = ${source.concatTokens()}.\n` + indentation);
56428
+ const fix2 = edit_helper_1.EditHelper.replaceRange(lowFile, source.getFirstToken().getStart(), source.getLastToken().getEnd(), uniqueName);
56429
+ const fix = edit_helper_1.EditHelper.merge(fix2, fix1);
56430
+ return issue_1.Issue.atToken(lowFile, high.getFirstToken(), "Outline message source", this.getMetadata().key, this.conf.severity, fix);
56431
+ }
56432
+ return undefined;
56433
+ }
55924
56434
  replaceInsertExpression(high, lowFile, highSyntax) {
55925
56435
  if (!(high.get() instanceof Statements.InsertInternal)) {
55926
56436
  return undefined;
@@ -58255,6 +58765,8 @@ class EmptyStatement extends _abap_rule_1.ABAPRule {
58255
58765
  title: "Remove empty statement",
58256
58766
  shortDescription: `Checks for empty statements (an empty statement is a single dot)`,
58257
58767
  tags: [_irule_1.RuleTag.Quickfix, _irule_1.RuleTag.SingleFile],
58768
+ badExample: `WRITE 'hello world'..`,
58769
+ goodExample: `WRITE 'hello world'.`,
58258
58770
  };
58259
58771
  }
58260
58772
  getConfig() {
@@ -58305,6 +58817,8 @@ class EmptyStructureConf extends _basic_rule_config_1.BasicRuleConfig {
58305
58817
  super(...arguments);
58306
58818
  /** Checks for empty LOOP blocks */
58307
58819
  this.loop = true;
58820
+ /** Allow empty LOOP if subrc is checked after the loop */
58821
+ this.loopAllowIfSubrc = true;
58308
58822
  /** Checks for empty IF blocks */
58309
58823
  this.if = true;
58310
58824
  /** Checks for empty WHILE blocks */
@@ -58337,6 +58851,14 @@ class EmptyStructure extends _abap_rule_1.ABAPRule {
58337
58851
  shortDescription: `Checks that the code does not contain empty blocks.`,
58338
58852
  extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#no-empty-if-branches`,
58339
58853
  tags: [_irule_1.RuleTag.Styleguide, _irule_1.RuleTag.SingleFile],
58854
+ badExample: `IF foo = bar.
58855
+ ENDIF.
58856
+
58857
+ DO 2 TIMES.
58858
+ ENDDO.`,
58859
+ goodExample: `LOOP AT itab WHERE qty = 0 OR date > sy-datum.
58860
+ ENDLOOP.
58861
+ result = xsdbool( sy-subrc = 0 ).`,
58340
58862
  };
58341
58863
  }
58342
58864
  getDescription(name) {
@@ -58354,15 +58876,13 @@ class EmptyStructure extends _abap_rule_1.ABAPRule {
58354
58876
  if (stru === undefined) {
58355
58877
  return [];
58356
58878
  }
58357
- for (const statement of file.getStatements()) {
58879
+ const statements = file.getStatements();
58880
+ for (const statement of statements) {
58358
58881
  if (statement.get() instanceof _statement_1.Unknown) {
58359
58882
  return []; // contains parser errors
58360
58883
  }
58361
58884
  }
58362
58885
  const candidates = [];
58363
- if (this.getConfig().loop === true) {
58364
- candidates.push(...stru.findAllStructuresRecursive(Structures.Loop));
58365
- }
58366
58886
  if (this.getConfig().while === true) {
58367
58887
  candidates.push(...stru.findAllStructuresRecursive(Structures.While));
58368
58888
  }
@@ -58398,6 +58918,22 @@ class EmptyStructure extends _abap_rule_1.ABAPRule {
58398
58918
  }
58399
58919
  }
58400
58920
  }
58921
+ if (this.getConfig().loop === true) {
58922
+ const loops = stru.findAllStructuresRecursive(Structures.Loop);
58923
+ for (const loop of loops) {
58924
+ if (loop.getChildren().length === 2) {
58925
+ const endloopStatement = loop.getLastChild();
58926
+ const endloopIndex = statements.findIndex((s) => s === endloopStatement);
58927
+ const afterEndloop = statements[endloopIndex + 1];
58928
+ if (afterEndloop !== undefined && afterEndloop.concatTokens().toUpperCase().includes("SY-SUBRC")) {
58929
+ continue;
58930
+ }
58931
+ const token = loop.getFirstToken();
58932
+ const issue = issue_1.Issue.atToken(file, token, this.getDescription(loop.get().constructor.name), this.getMetadata().key, this.conf.severity);
58933
+ issues.push(issue);
58934
+ }
58935
+ }
58936
+ }
58401
58937
  if (this.getConfig().if === true) {
58402
58938
  const tries = stru.findAllStructuresRecursive(Structures.If)
58403
58939
  .concat(stru.findAllStructuresRecursive(Structures.Else))
@@ -60643,6 +61179,24 @@ class Indentation extends _abap_rule_1.ABAPRule {
60643
61179
  title: "Indentation",
60644
61180
  shortDescription: `Checks indentation`,
60645
61181
  tags: [_irule_1.RuleTag.Whitespace, _irule_1.RuleTag.Quickfix, _irule_1.RuleTag.SingleFile],
61182
+ badExample: `CLASS lcl DEFINITION.
61183
+ PRIVATE SECTION.
61184
+ METHODS constructor.
61185
+ ENDCLASS.
61186
+
61187
+ CLASS lcl IMPLEMENTATION.
61188
+ METHOD constructor.
61189
+ ENDMETHOD.
61190
+ ENDCLASS.`,
61191
+ goodExample: `CLASS lcl DEFINITION.
61192
+ PRIVATE SECTION.
61193
+ METHODS constructor.
61194
+ ENDCLASS.
61195
+
61196
+ CLASS lcl IMPLEMENTATION.
61197
+ METHOD constructor.
61198
+ ENDMETHOD.
61199
+ ENDCLASS.`,
60646
61200
  };
60647
61201
  }
60648
61202
  getConfig() {
@@ -60754,6 +61308,8 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
60754
61308
  __exportStar(__webpack_require__(/*! ./7bit_ascii */ "./node_modules/@abaplint/core/build/src/rules/7bit_ascii.js"), exports);
60755
61309
  __exportStar(__webpack_require__(/*! ./abapdoc */ "./node_modules/@abaplint/core/build/src/rules/abapdoc.js"), exports);
60756
61310
  __exportStar(__webpack_require__(/*! ./align_parameters */ "./node_modules/@abaplint/core/build/src/rules/align_parameters.js"), exports);
61311
+ __exportStar(__webpack_require__(/*! ./align_pseudo_comments */ "./node_modules/@abaplint/core/build/src/rules/align_pseudo_comments.js"), exports);
61312
+ __exportStar(__webpack_require__(/*! ./align_type_expressions */ "./node_modules/@abaplint/core/build/src/rules/align_type_expressions.js"), exports);
60757
61313
  __exportStar(__webpack_require__(/*! ./allowed_object_naming */ "./node_modules/@abaplint/core/build/src/rules/allowed_object_naming.js"), exports);
60758
61314
  __exportStar(__webpack_require__(/*! ./allowed_object_types */ "./node_modules/@abaplint/core/build/src/rules/allowed_object_types.js"), exports);
60759
61315
  __exportStar(__webpack_require__(/*! ./ambiguous_statement */ "./node_modules/@abaplint/core/build/src/rules/ambiguous_statement.js"), exports);
@@ -61455,6 +62011,8 @@ class KeywordCase extends _abap_rule_1.ABAPRule {
61455
62011
  shortDescription: `Checks that keywords have the same case. Non-keywords must be lower case.`,
61456
62012
  extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#use-your-pretty-printer-team-settings`,
61457
62013
  tags: [_irule_1.RuleTag.Styleguide, _irule_1.RuleTag.SingleFile, _irule_1.RuleTag.Quickfix],
62014
+ badExample: `write 'hello world'.`,
62015
+ goodExample: `WRITE 'hello world'.`,
61458
62016
  };
61459
62017
  }
61460
62018
  getConfig() {
@@ -61542,8 +62100,11 @@ class KeywordCase extends _abap_rule_1.ABAPRule {
61542
62100
  /** returns a list of tokens which violates the keyword_case rule */
61543
62101
  traverse(s, parent) {
61544
62102
  let ret = [];
61545
- for (const child of s.getChildren()) {
62103
+ const children = s.getChildren();
62104
+ for (let i = 0; i < children.length; i++) {
62105
+ const child = children[i];
61546
62106
  if (child instanceof nodes_1.TokenNodeRegex) {
62107
+ const next = children[i + 1];
61547
62108
  if (this.conf.ignoreLowerClassImplmentationStatement
61548
62109
  && parent instanceof Statements.ClassImplementation) {
61549
62110
  continue;
@@ -61551,7 +62112,7 @@ class KeywordCase extends _abap_rule_1.ABAPRule {
61551
62112
  const str = child.get().getStr();
61552
62113
  const upper = str.toUpperCase();
61553
62114
  // todo, this is a hack, the parser should recongize OTHERS/TEXT as a keyword
61554
- if (upper === "OTHERS" || upper === "TEXT") {
62115
+ if (upper === "OTHERS" || (upper === "TEXT" && (next === null || next === void 0 ? void 0 : next.concatTokens()) === "-")) {
61555
62116
  continue;
61556
62117
  }
61557
62118
  if (this.conf.ignoreFunctionModuleName === true
@@ -62116,6 +62677,12 @@ class LocalVariableNames extends _abap_rule_1.ABAPRule {
62116
62677
  Allows you to enforce a pattern, such as a prefix, for local variables, constants and field symbols.
62117
62678
  Regexes are case-insensitive.`,
62118
62679
  tags: [_irule_1.RuleTag.Naming, _irule_1.RuleTag.SingleFile],
62680
+ badExample: `FORM bar.
62681
+ DATA foo.
62682
+ ENDFORM.`,
62683
+ goodExample: `FORM bar.
62684
+ DATA lv_foo.
62685
+ ENDFORM.`,
62119
62686
  };
62120
62687
  }
62121
62688
  getDescription(expected, actual) {
@@ -63089,6 +63656,15 @@ https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#avoid-obscu
63089
63656
 
63090
63657
  Interface method names are ignored`,
63091
63658
  tags: [_irule_1.RuleTag.Naming, _irule_1.RuleTag.SingleFile, _irule_1.RuleTag.Styleguide],
63659
+ badExample: `CLASS lcl DEFINITION.
63660
+ PUBLIC SECTION.
63661
+ METHODS matches.
63662
+ ENDCLASS.
63663
+
63664
+ CLASS lcl IMPLEMENTATION.
63665
+ METHOD matches.
63666
+ ENDMETHOD.
63667
+ ENDCLASS.`,
63092
63668
  };
63093
63669
  }
63094
63670
  getConfig() {
@@ -63278,6 +63854,13 @@ class MixReturning extends _abap_rule_1.ABAPRule {
63278
63854
  // eslint-disable-next-line max-len
63279
63855
  extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#use-either-returning-or-exporting-or-changing-but-not-a-combination`,
63280
63856
  tags: [_irule_1.RuleTag.Styleguide, _irule_1.RuleTag.SingleFile],
63857
+ badExample: `CLASS lcl DEFINITION.
63858
+ PUBLIC SECTION.
63859
+ METHODS
63860
+ foobar
63861
+ EXPORTING foo TYPE i
63862
+ RETURNING VALUE(rv_string) TYPE string.
63863
+ ENDCLASS.`,
63281
63864
  };
63282
63865
  }
63283
63866
  getMessage() {
@@ -64109,6 +64692,7 @@ class NoPrefixesConf extends _basic_rule_config_1.BasicRuleConfig {
64109
64692
  this.types = "^TY_";
64110
64693
  /** importing, exporting, returning and changing parameters, case insensitive regex */
64111
64694
  this.methodParameters = "^[ICER].?_";
64695
+ this.allowIsPrefixBoolean = true;
64112
64696
  // todo, public localClass: string = "";
64113
64697
  // todo, public localInterface: string = "";
64114
64698
  // todo, public functionModuleParameters: string = "";
@@ -64253,12 +64837,18 @@ https://github.com/SAP/styleguides/blob/main/clean-abap/sub-sections/AvoidEncodi
64253
64837
  return ret;
64254
64838
  }
64255
64839
  checkMethodParameters(topNode, regex, file) {
64840
+ var _a, _b;
64256
64841
  const ret = [];
64257
64842
  for (const method of topNode.findAllStatements(Statements.MethodDef)) {
64258
- for (const def of method.findAllExpressions(Expressions.MethodParamName)) {
64259
- const name = def.concatTokens();
64260
- if (name !== "" && name.match(regex)) {
64261
- const issue = issue_1.Issue.atToken(file, def.getFirstToken(), MESSAGE, this.getMetadata().key, this.conf.severity);
64843
+ for (const param of method.findAllExpressionsMulti([Expressions.MethodDefReturning, Expressions.MethodParam])) {
64844
+ const nameToken = param === null || param === void 0 ? void 0 : param.findFirstExpression(Expressions.MethodParamName);
64845
+ const type = (_b = (_a = param === null || param === void 0 ? void 0 : param.findFirstExpression(Expressions.TypeParam)) === null || _a === void 0 ? void 0 : _a.concatTokens()) === null || _b === void 0 ? void 0 : _b.toUpperCase();
64846
+ if (this.getConfig().allowIsPrefixBoolean === true && (type === null || type === void 0 ? void 0 : type.endsWith("TYPE ABAP_BOOL"))) {
64847
+ continue;
64848
+ }
64849
+ const name = nameToken === null || nameToken === void 0 ? void 0 : nameToken.concatTokens();
64850
+ if (nameToken && name && name !== "" && name.match(regex)) {
64851
+ const issue = issue_1.Issue.atToken(file, nameToken.getFirstToken(), MESSAGE, this.getMetadata().key, this.conf.severity);
64262
64852
  ret.push(issue);
64263
64853
  }
64264
64854
  }
@@ -66567,6 +67157,10 @@ class PreferReturningToExporting extends _abap_rule_1.ABAPRule {
66567
67157
  extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#prefer-returning-to-exporting
66568
67158
  https://docs.abapopenchecks.org/checks/44/`,
66569
67159
  tags: [_irule_1.RuleTag.Styleguide, _irule_1.RuleTag.SingleFile],
67160
+ badExample: `CLASS lcl DEFINITION.
67161
+ PUBLIC SECTION.
67162
+ METHODS test EXPORTING ev_foo TYPE i.
67163
+ ENDCLASS.`,
66570
67164
  };
66571
67165
  }
66572
67166
  getConfig() {
@@ -66734,6 +67328,10 @@ class PreferredCompareOperator extends _abap_rule_1.ABAPRule {
66734
67328
  title: "Preferred compare operator",
66735
67329
  shortDescription: `Configure undesired operator variants`,
66736
67330
  tags: [_irule_1.RuleTag.SingleFile, _irule_1.RuleTag.Quickfix],
67331
+ badExample: `IF foo EQ bar.
67332
+ ENDIF.`,
67333
+ goodExample: `IF foo = bar.
67334
+ ENDIF.`,
66737
67335
  };
66738
67336
  }
66739
67337
  getDescription(operator) {
@@ -67447,6 +68045,8 @@ add ORDER BY PRIMARY KEY if in doubt
67447
68045
 
67448
68046
  If the target is a sorted/hashed table, no issue is reported`,
67449
68047
  tags: [_irule_1.RuleTag.SingleFile],
68048
+ badExample: `SELECT * FROM db INTO TABLE @DATA(tab).`,
68049
+ goodExample: `SELECT * FROM db INTO TABLE @DATA(tab) ORDER BY PRIMARY KEY.`,
67450
68050
  };
67451
68051
  }
67452
68052
  getConfig() {
@@ -67675,7 +68275,9 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
67675
68275
  exports.SelectSingleFullKey = exports.SelectSingleFullKeyConf = void 0;
67676
68276
  const issue_1 = __webpack_require__(/*! ../issue */ "./node_modules/@abaplint/core/build/src/issue.js");
67677
68277
  const _basic_rule_config_1 = __webpack_require__(/*! ./_basic_rule_config */ "./node_modules/@abaplint/core/build/src/rules/_basic_rule_config.js");
68278
+ const _irule_1 = __webpack_require__(/*! ./_irule */ "./node_modules/@abaplint/core/build/src/rules/_irule.js");
67678
68279
  const __1 = __webpack_require__(/*! .. */ "./node_modules/@abaplint/core/build/src/index.js");
68280
+ const edit_helper_1 = __webpack_require__(/*! ../edit_helper */ "./node_modules/@abaplint/core/build/src/edit_helper.js");
67679
68281
  class SelectSingleFullKeyConf extends _basic_rule_config_1.BasicRuleConfig {
67680
68282
  constructor() {
67681
68283
  super(...arguments);
@@ -67696,7 +68298,7 @@ class SelectSingleFullKey {
67696
68298
 
67697
68299
  If the statement contains a JOIN it is not checked`,
67698
68300
  pseudoComment: "EC CI_NOORDER",
67699
- tags: [],
68301
+ tags: [_irule_1.RuleTag.Quickfix],
67700
68302
  };
67701
68303
  }
67702
68304
  initialize(reg) {
@@ -67717,6 +68319,12 @@ If the statement contains a JOIN it is not checked`,
67717
68319
  setConfig(conf) {
67718
68320
  this.conf = conf;
67719
68321
  }
68322
+ buildFix(file, statement) {
68323
+ return {
68324
+ description: `Add "#EC CI_NOORDER`,
68325
+ edit: edit_helper_1.EditHelper.insertAt(file, statement.getLastToken().getStart(), ` "#EC CI_NOORDER`),
68326
+ };
68327
+ }
67720
68328
  run(obj) {
67721
68329
  var _a, _b;
67722
68330
  if (!(obj instanceof __1.ABAPObject)) {
@@ -67778,7 +68386,8 @@ If the statement contains a JOIN it is not checked`,
67778
68386
  }
67779
68387
  }
67780
68388
  if (set.size > 0) {
67781
- issues.push(issue_1.Issue.atStatement(file, s, message, this.getMetadata().key, this.getConfig().severity));
68389
+ const fix = this.buildFix(file, s);
68390
+ issues.push(issue_1.Issue.atStatement(file, s, message, this.getMetadata().key, this.getConfig().severity, undefined, [fix]));
67782
68391
  }
67783
68392
  }
67784
68393
  }
@@ -69464,6 +70073,8 @@ class TypesNaming extends _abap_rule_1.ABAPRule {
69464
70073
  shortDescription: `Allows you to enforce a pattern for TYPES definitions`,
69465
70074
  extendedInformation: `Does not run for TYPE POOLS`,
69466
70075
  tags: [_irule_1.RuleTag.Naming, _irule_1.RuleTag.SingleFile],
70076
+ badExample: `TYPES foo TYPE i.`,
70077
+ goodExample: `TYPES ty_foo TYPE i.`,
69467
70078
  };
69468
70079
  }
69469
70080
  getConfig() {
@@ -70241,7 +70852,13 @@ const _basic_rule_config_1 = __webpack_require__(/*! ./_basic_rule_config */ "./
70241
70852
  const _irule_1 = __webpack_require__(/*! ./_irule */ "./node_modules/@abaplint/core/build/src/rules/_irule.js");
70242
70853
  const Statements = __webpack_require__(/*! ../abap/2_statements/statements */ "./node_modules/@abaplint/core/build/src/abap/2_statements/statements/index.js");
70243
70854
  const edit_helper_1 = __webpack_require__(/*! ../edit_helper */ "./node_modules/@abaplint/core/build/src/edit_helper.js");
70855
+ const _statement_1 = __webpack_require__(/*! ../abap/2_statements/statements/_statement */ "./node_modules/@abaplint/core/build/src/abap/2_statements/statements/_statement.js");
70244
70856
  class UnnecessaryReturnConf extends _basic_rule_config_1.BasicRuleConfig {
70857
+ constructor() {
70858
+ super(...arguments);
70859
+ /** Allow empty METHODs + FORMs + FUNCTION-MODULEs */
70860
+ this.allowEmpty = false;
70861
+ }
70245
70862
  }
70246
70863
  exports.UnnecessaryReturnConf = UnnecessaryReturnConf;
70247
70864
  class UnnecessaryReturn extends _abap_rule_1.ABAPRule {
@@ -70285,15 +70902,29 @@ ENDFORM.`,
70285
70902
  }
70286
70903
  const message = "Unnecessary RETURN";
70287
70904
  const statements = file.getStatements();
70905
+ let statementCounter = 0;
70288
70906
  for (let i = 0; i < statements.length; i++) {
70289
70907
  const node = statements[i];
70290
- if (!(node.get() instanceof Statements.EndMethod
70291
- || node.get() instanceof Statements.EndForm
70292
- || node.get() instanceof Statements.EndFunction)) {
70908
+ const nodeType = node.get();
70909
+ if ((nodeType instanceof Statements.MethodImplementation
70910
+ || nodeType instanceof Statements.Form
70911
+ || nodeType instanceof Statements.FunctionModule)) {
70912
+ statementCounter = 0;
70913
+ continue;
70914
+ }
70915
+ if (!(nodeType instanceof _statement_1.Comment)) {
70916
+ statementCounter++;
70917
+ }
70918
+ if (!(nodeType instanceof Statements.EndMethod
70919
+ || nodeType instanceof Statements.EndForm
70920
+ || nodeType instanceof Statements.EndFunction)) {
70293
70921
  continue;
70294
70922
  }
70295
70923
  const prev = statements[i - 1];
70296
70924
  if (prev && prev.get() instanceof Statements.Return) {
70925
+ if (this.conf.allowEmpty === true && statementCounter === 2) {
70926
+ continue;
70927
+ }
70297
70928
  const fix = edit_helper_1.EditHelper.deleteStatement(file, prev);
70298
70929
  issues.push(issue_1.Issue.atStatement(file, prev, message, this.getMetadata().key, this.getConfig().severity, fix));
70299
70930
  }
@@ -70648,6 +71279,7 @@ Skips:
70648
71279
  `,
70649
71280
  tags: [],
70650
71281
  pragma: "##CALLED",
71282
+ pseudoComment: "EC CALLED",
70651
71283
  };
70652
71284
  }
70653
71285
  getConfig() {
@@ -70724,11 +71356,32 @@ Skips:
70724
71356
  if (statement.getPragmas().some(t => t.getStr() === this.getMetadata().pragma)) {
70725
71357
  continue;
70726
71358
  }
71359
+ else if (this.suppressedbyPseudo(statement, file)) {
71360
+ continue;
71361
+ }
70727
71362
  const message = "Method \"" + i.identifier.getName() + "\" not used";
70728
71363
  issues.push(issue_1.Issue.atIdentifier(i.identifier, message, this.getMetadata().key, this.conf.severity));
70729
71364
  }
70730
71365
  return issues;
70731
71366
  }
71367
+ suppressedbyPseudo(statement, file) {
71368
+ if (statement === undefined) {
71369
+ return false;
71370
+ }
71371
+ if (file === undefined) {
71372
+ return false;
71373
+ }
71374
+ let next = false;
71375
+ for (const s of file.getStatements()) {
71376
+ if (next === true && s.get() instanceof _statement_1.Comment) {
71377
+ return s.concatTokens().includes(this.getMetadata().pseudoComment + "");
71378
+ }
71379
+ if (s === statement) {
71380
+ next = true;
71381
+ }
71382
+ }
71383
+ return false;
71384
+ }
70732
71385
  searchGlobalSubclasses(obj) {
70733
71386
  var _a, _b;
70734
71387
  if (this.wa.getLength() === 0
@@ -70839,6 +71492,7 @@ class UnusedTypes {
70839
71492
  extendedInformation: `Unused types are not reported if the object contains parser or syntax errors.`,
70840
71493
  tags: [_irule_1.RuleTag.Quickfix],
70841
71494
  pragma: "##NEEDED",
71495
+ pseudoComment: "EC NEEDED",
70842
71496
  };
70843
71497
  }
70844
71498
  getConfig() {
@@ -70906,11 +71560,32 @@ class UnusedTypes {
70906
71560
  if (statement.getPragmas().some(t => t.getStr() === this.getMetadata().pragma)) {
70907
71561
  continue;
70908
71562
  }
71563
+ else if (this.suppressedbyPseudo(statement, file)) {
71564
+ continue;
71565
+ }
70909
71566
  const fix = this.buildFix(file, statement);
70910
71567
  ret.push(issue_1.Issue.atIdentifier(t, message, this.getMetadata().key, this.conf.severity, fix));
70911
71568
  }
70912
71569
  return ret;
70913
71570
  }
71571
+ suppressedbyPseudo(statement, file) {
71572
+ if (statement === undefined) {
71573
+ return false;
71574
+ }
71575
+ if (file === undefined) {
71576
+ return false;
71577
+ }
71578
+ let next = false;
71579
+ for (const s of file.getStatements()) {
71580
+ if (next === true && s.get() instanceof _statement_1.Comment) {
71581
+ return s.concatTokens().includes(this.getMetadata().pseudoComment + "");
71582
+ }
71583
+ if (s === statement) {
71584
+ next = true;
71585
+ }
71586
+ }
71587
+ return false;
71588
+ }
70914
71589
  ////////////////////////////
70915
71590
  traverse(node, obj, add) {
70916
71591
  if (node.getIdentifier().stype !== _scope_type_1.ScopeType.BuiltIn) {
@@ -71395,6 +72070,16 @@ class UseClassBasedExceptions extends _abap_rule_1.ABAPRule {
71395
72070
  shortDescription: `Use class based exceptions, checks interface and class definitions`,
71396
72071
  extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#use-class-based-exceptions`,
71397
72072
  tags: [_irule_1.RuleTag.Styleguide, _irule_1.RuleTag.SingleFile],
72073
+ badExample: `INTERFACE lif.
72074
+ METHODS load_data
72075
+ EXCEPTIONS
72076
+ invalid_parameter.
72077
+ ENDINTERFACE.`,
72078
+ goodExample: `INTERFACE lif.
72079
+ METHODS load_data
72080
+ RAISING
72081
+ cx_something.
72082
+ ENDINTERFACE.`,
71398
72083
  };
71399
72084
  }
71400
72085
  getMessage() {
@@ -76945,12 +77630,12 @@ class Transpiler {
76945
77630
  progress?.set(reg.getObjectCount(false), "Building");
76946
77631
  for (const obj of reg.getObjects()) {
76947
77632
  await progress?.tick("Building, " + obj.getName());
76948
- if (obj instanceof abaplint.ABAPObject && !(obj instanceof abaplint.Objects.TypePool)) {
76949
- output.objects.push(...new handle_abap_1.HandleABAP(this.options).runObject(obj, reg));
76950
- }
76951
- else if (obj instanceof abaplint.Objects.TypePool) {
77633
+ if (obj instanceof abaplint.Objects.TypePool) {
76952
77634
  output.objects.push(...new handle_type_pool_1.HandleTypePool().runObject(obj, reg));
76953
77635
  }
77636
+ else if (obj instanceof abaplint.ABAPObject) {
77637
+ output.objects.push(...new handle_abap_1.HandleABAP(this.options).runObject(obj, reg));
77638
+ }
76954
77639
  else if (obj instanceof abaplint.Objects.Oauth2Profile) {
76955
77640
  output.objects.push(...new handle_oa2p_1.HandleOA2P().runObject(obj, reg));
76956
77641
  }
@@ -85227,28 +85912,29 @@ async function run() {
85227
85912
  for (const st of this.getSortedTests(reg)) {
85228
85913
  ret += `// --------------------------------------------\n`;
85229
85914
  ret += ` clas = unit.addObject("${st.obj.getName()}");\n`;
85915
+ const lc = st.localClass.toLowerCase();
85230
85916
  ret += ` {
85231
- const {${st.localClass}} = await import("./${this.escapeNamespace(st.obj.getName().toLowerCase())}.${st.obj.getType().toLowerCase()}.testclasses.mjs");
85232
- locl = clas.addTestClass("${st.localClass}");
85233
- if (${st.localClass}.class_setup) await ${st.localClass}.class_setup();\n`;
85917
+ const {${lc}} = await import("./${this.escapeNamespace(st.obj.getName().toLowerCase())}.${st.obj.getType().toLowerCase()}.testclasses.mjs");
85918
+ locl = clas.addTestClass("${lc}");
85919
+ if (${lc}.class_setup) await ${lc}.class_setup();\n`;
85234
85920
  for (const m of st.methods) {
85235
- const skipThis = (skip || []).some(a => a.object === st.obj.getName() && a.class === st.localClass && a.method === m);
85921
+ const skipThis = (skip || []).some(a => a.object === st.obj.getName() && a.class === lc && a.method === m);
85236
85922
  if (skipThis) {
85237
- ret += ` console.log('${st.obj.getName()}: running ${st.localClass}->${m}, skipped');\n`;
85923
+ ret += ` console.log('${st.obj.getName()}: running ${lc}->${m}, skipped');\n`;
85238
85924
  ret += ` meth = locl.addMethod("${m}");\n`;
85239
85925
  ret += ` meth.skip();\n`;
85240
85926
  continue;
85241
85927
  }
85242
- ret += ` {\n const test = await (new ${st.localClass}()).constructor_();\n`;
85928
+ ret += ` {\n const test = await (new ${lc}()).constructor_();\n`;
85243
85929
  ret += ` if (test.setup) await test.setup();\n`;
85244
- ret += ` console.log("${st.obj.getName()}: running ${st.localClass}->${m}");\n`;
85930
+ ret += ` console.log("${st.obj.getName()}: running ${lc}->${m}");\n`;
85245
85931
  ret += ` meth = locl.addMethod("${m}");\n`;
85246
85932
  ret += ` await test.${m}();\n`;
85247
85933
  ret += ` meth.pass();\n`;
85248
85934
  ret += ` if (test.teardown) await test.teardown();\n`;
85249
85935
  ret += ` }\n`;
85250
85936
  }
85251
- ret += ` if (${st.localClass}.class_teardown) await ${st.localClass}.class_teardown();\n`;
85937
+ ret += ` if (${lc}.class_teardown) await ${lc}.class_teardown();\n`;
85252
85938
  ret += ` }\n`;
85253
85939
  }
85254
85940
  /*
@@ -86070,6 +86756,8 @@ exports.validate = function (xmlData, options) {
86070
86756
  return getErrorObject('InvalidTag', "Closing tag '"+tagName+"' doesn't have proper closing.", getLineNumberForPosition(xmlData, i));
86071
86757
  } else if (attrStr.trim().length > 0) {
86072
86758
  return getErrorObject('InvalidTag', "Closing tag '"+tagName+"' can't have attributes or invalid starting.", getLineNumberForPosition(xmlData, tagStartPos));
86759
+ } else if (tags.length === 0) {
86760
+ return getErrorObject('InvalidTag', "Closing tag '"+tagName+"' has not been opened.", getLineNumberForPosition(xmlData, tagStartPos));
86073
86761
  } else {
86074
86762
  const otg = tags.pop();
86075
86763
  if (tagName !== otg.tagName) {
@@ -87357,10 +88045,18 @@ const parseXml = function(xmlData) {
87357
88045
  let tagContent = "";
87358
88046
  //self-closing tag
87359
88047
  if(tagExp.length > 0 && tagExp.lastIndexOf("/") === tagExp.length - 1){
88048
+ if(tagName[tagName.length - 1] === "/"){ //remove trailing '/'
88049
+ tagName = tagName.substr(0, tagName.length - 1);
88050
+ jPath = jPath.substr(0, jPath.length - 1);
88051
+ tagExp = tagName;
88052
+ }else{
88053
+ tagExp = tagExp.substr(0, tagExp.length - 1);
88054
+ }
87360
88055
  i = result.closeIndex;
87361
88056
  }
87362
88057
  //unpaired tag
87363
88058
  else if(this.options.unpairedTags.indexOf(tagName) !== -1){
88059
+
87364
88060
  i = result.closeIndex;
87365
88061
  }
87366
88062
  //normal tag