@abaplint/core 2.79.30 → 2.79.34

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.
@@ -1655,6 +1655,7 @@ declare namespace Expressions {
1655
1655
  ClassGlobal_2 as ClassGlobal,
1656
1656
  ClassName,
1657
1657
  Color,
1658
+ FindType,
1658
1659
  CompareOperator,
1659
1660
  Compare,
1660
1661
  ComponentChainSimple,
@@ -1915,6 +1916,10 @@ declare class Find implements IStatement {
1915
1916
  getMatcher(): IStatementRunnable;
1916
1917
  }
1917
1918
 
1919
+ declare class FindType extends Expression {
1920
+ getRunnable(): IStatementRunnable;
1921
+ }
1922
+
1918
1923
  declare class FloatingPointType extends AbstractType {
1919
1924
  private readonly length;
1920
1925
  constructor(length: number, qualifiedName?: string);
@@ -2615,6 +2620,7 @@ declare interface IMethodParameters {
2615
2620
  getOptional(): readonly string[];
2616
2621
  getReturning(): TypedIdentifier | undefined;
2617
2622
  getExceptions(): readonly string[];
2623
+ getFilename(): string;
2618
2624
  getDefaultImporting(): string | undefined;
2619
2625
  getParameterDefault(parameter: string): ExpressionNode | undefined;
2620
2626
  }
@@ -3483,6 +3489,7 @@ declare class MethodParameters_2 implements IMethodParameters {
3483
3489
  private readonly defaults;
3484
3490
  private readonly filename;
3485
3491
  constructor(node: StatementNode, filename: string, scope: CurrentScope);
3492
+ getFilename(): string;
3486
3493
  getOptional(): string[];
3487
3494
  getAll(): TypedIdentifier[];
3488
3495
  getDefaultImporting(): string | undefined;
@@ -6,9 +6,9 @@ const _1 = require(".");
6
6
  const tokens_1 = require("../../1_lexer/tokens");
7
7
  class FieldChain extends combi_1.Expression {
8
8
  getRunnable() {
9
- const attr = (0, combi_1.seq)((0, combi_1.tok)(tokens_1.InstanceArrow), (0, combi_1.altPrio)(_1.AttributeName, "*"));
9
+ const attr = (0, combi_1.seq)((0, combi_1.tok)(tokens_1.InstanceArrow), _1.AttributeName);
10
10
  const comp = (0, combi_1.seq)((0, combi_1.tok)(tokens_1.Dash), (0, combi_1.optPrio)(_1.ComponentName));
11
- const chain = (0, combi_1.star)((0, combi_1.altPrio)(attr, comp, _1.TableExpression));
11
+ const chain = (0, combi_1.star)((0, combi_1.altPrio)(_1.Dereference, attr, comp, _1.TableExpression));
12
12
  const clas = (0, combi_1.seq)(_1.ClassName, (0, combi_1.tok)(tokens_1.StaticArrow), _1.AttributeName);
13
13
  const start = (0, combi_1.altPrio)(clas, _1.SourceField, _1.SourceFieldSymbol);
14
14
  const after = (0, combi_1.altPrio)((0, combi_1.tok)(tokens_1.DashW), (0, combi_1.seq)((0, combi_1.optPrio)(_1.TableBody), (0, combi_1.optPrio)(_1.FieldOffset), (0, combi_1.optPrio)(_1.FieldLength)));
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FindType = void 0;
4
+ const version_1 = require("../../../version");
5
+ const combi_1 = require("../combi");
6
+ class FindType extends combi_1.Expression {
7
+ getRunnable() {
8
+ return (0, combi_1.opt)((0, combi_1.alt)("REGEX", "SUBSTRING", (0, combi_1.ver)(version_1.Version.v755, "PCRE")));
9
+ }
10
+ }
11
+ exports.FindType = FindType;
12
+ //# sourceMappingURL=find_type.js.map
@@ -27,6 +27,7 @@ __exportStar(require("./class_friends"), exports);
27
27
  __exportStar(require("./class_global"), exports);
28
28
  __exportStar(require("./class_name"), exports);
29
29
  __exportStar(require("./color"), exports);
30
+ __exportStar(require("./find_type"), exports);
30
31
  __exportStar(require("./compare_operator"), exports);
31
32
  __exportStar(require("./compare"), exports);
32
33
  __exportStar(require("./component_chain_simple"), exports);
@@ -3,14 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Find = void 0;
4
4
  const combi_1 = require("../combi");
5
5
  const expressions_1 = require("../expressions");
6
- const version_1 = require("../../../version");
7
6
  class Find {
8
7
  getMatcher() {
9
8
  // SUBMATCHES handling is a workaround
10
9
  const options = (0, combi_1.per)("IGNORING CASE", "RESPECTING CASE", "IN BYTE MODE", "IN CHARACTER MODE", (0, combi_1.seq)("OF", expressions_1.Source), (0, combi_1.seq)("FROM", expressions_1.Source), (0, combi_1.seq)("TO", expressions_1.Source), (0, combi_1.seq)("MATCH OFFSET", expressions_1.Target), (0, combi_1.seq)("MATCH LINE", expressions_1.Target), (0, combi_1.seq)("MATCH COUNT", expressions_1.Target), (0, combi_1.seq)("MATCH LENGTH", expressions_1.Target), (0, combi_1.seq)("LENGTH", expressions_1.Source), (0, combi_1.seq)("RESULTS", expressions_1.Target), (0, combi_1.seq)("SUBMATCHES", expressions_1.Target), (0, combi_1.seq)("SUBMATCHES", expressions_1.Target, expressions_1.Target), (0, combi_1.seq)("SUBMATCHES", (0, combi_1.plus)(expressions_1.Target)));
11
10
  const sectionLength = (0, combi_1.seq)("SECTION LENGTH", expressions_1.Source, "OF");
12
11
  const before = (0, combi_1.seq)((0, combi_1.optPrio)((0, combi_1.alt)("TABLE", "SECTION OFFSET", sectionLength)), expressions_1.Source);
13
- const ret = (0, combi_1.seq)("FIND", (0, combi_1.opt)((0, combi_1.alt)("FIRST OCCURRENCE OF", "ALL OCCURRENCES OF")), (0, combi_1.opt)((0, combi_1.alt)("REGEX", "SUBSTRING", (0, combi_1.ver)(version_1.Version.v755, "PCRE"))), expressions_1.Source, "IN", before, (0, combi_1.opt)(options));
12
+ const ret = (0, combi_1.seq)("FIND", (0, combi_1.opt)((0, combi_1.alt)("FIRST OCCURRENCE OF", "ALL OCCURRENCES OF")), expressions_1.FindType, expressions_1.Source, "IN", before, (0, combi_1.opt)(options));
14
13
  return ret;
15
14
  }
16
15
  }
@@ -3,13 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Replace = void 0;
4
4
  const combi_1 = require("../combi");
5
5
  const expressions_1 = require("../expressions");
6
- const version_1 = require("../../../version");
7
6
  class Replace {
8
7
  getMatcher() {
9
8
  const length = (0, combi_1.seq)("LENGTH", expressions_1.Source);
10
9
  const offset = (0, combi_1.seq)("OFFSET", expressions_1.Source);
11
10
  const section = (0, combi_1.seq)((0, combi_1.opt)("IN"), "SECTION", (0, combi_1.per)(offset, length), "OF", expressions_1.Source);
12
- const source = (0, combi_1.seq)((0, combi_1.opt)("OF"), (0, combi_1.opt)((0, combi_1.alt)("REGEX", "SUBSTRING", (0, combi_1.ver)(version_1.Version.v755, "PCRE"))), expressions_1.Source);
11
+ const source = (0, combi_1.seq)((0, combi_1.opt)("OF"), expressions_1.FindType, expressions_1.Source);
13
12
  const cas = (0, combi_1.alt)("IGNORING CASE", "RESPECTING CASE");
14
13
  const repl = (0, combi_1.seq)("REPLACEMENT COUNT", expressions_1.Target);
15
14
  const replo = (0, combi_1.seq)("REPLACEMENT OFFSET", expressions_1.Target);
@@ -11,6 +11,8 @@ const _reference_1 = require("../_reference");
11
11
  const field_offset_1 = require("./field_offset");
12
12
  const field_length_1 = require("./field_length");
13
13
  const table_expression_1 = require("./table_expression");
14
+ const expressions_1 = require("../../2_statements/expressions");
15
+ const dereference_1 = require("./dereference");
14
16
  class FieldChain {
15
17
  runSyntax(node, scope, filename, refType) {
16
18
  const concat = node.concatTokens();
@@ -64,6 +66,9 @@ class FieldChain {
64
66
  throw new Error("Not a object reference, field chain");
65
67
  }
66
68
  }
69
+ else if (current.get() instanceof expressions_1.Dereference) {
70
+ context = new dereference_1.Dereference().runSyntax(context);
71
+ }
67
72
  else if (current.get() instanceof Expressions.ComponentName) {
68
73
  context = new component_name_1.ComponentName().runSyntax(context, current);
69
74
  }
@@ -29,6 +29,9 @@ class MethodParameters {
29
29
  this.filename = filename;
30
30
  this.parse(node, scope, filename);
31
31
  }
32
+ getFilename() {
33
+ return this.filename;
34
+ }
32
35
  getOptional() {
33
36
  return this.optional;
34
37
  }
@@ -68,7 +68,7 @@ class Registry {
68
68
  }
69
69
  static abaplintVersion() {
70
70
  // magic, see build script "version.sh"
71
- return "2.79.30";
71
+ return "2.79.34";
72
72
  }
73
73
  getDDICReferences() {
74
74
  return this.references;
@@ -42,7 +42,7 @@ class AllowedObjectNaming {
42
42
  message = "Name not allowed";
43
43
  }
44
44
  }
45
- else if (obj.getName().match(/^(\/[A-Z_\d]{3,8}\/)?[A-Z_\d<> ]+$/i) === null) {
45
+ else if (obj.getName().match(/^(\/[A-Z_\d]{3,8}\/)?[A-Z_-\d<> ]+$/i) === null) {
46
46
  message = "Name not allowed";
47
47
  }
48
48
  if (message.length > 0) {
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DangerousStatement = exports.DangerousStatementConf = void 0;
4
4
  const Statements = require("../abap/2_statements/statements");
5
+ const Expressions = require("../abap/2_statements/expressions");
5
6
  const issue_1 = require("../issue");
6
7
  const _abap_rule_1 = require("./_abap_rule");
7
8
  const _basic_rule_config_1 = require("./_basic_rule_config");
@@ -24,6 +25,8 @@ class DangerousStatementConf extends _basic_rule_config_1.BasicRuleConfig {
24
25
  this.deleteTextpool = true;
25
26
  this.deleteDynpro = true;
26
27
  this.importDynpro = true;
28
+ /** Finds instances of dynamic SQL: SELECT, UPDATE, DELETE, INSERT, MODIFY */
29
+ this.dynamicSQL = true;
27
30
  }
28
31
  }
29
32
  exports.DangerousStatementConf = DangerousStatementConf;
@@ -37,6 +40,7 @@ class DangerousStatement extends _abap_rule_1.ABAPRule {
37
40
  key: "dangerous_statement",
38
41
  title: "Dangerous statement",
39
42
  shortDescription: `Detects potentially dangerous statements`,
43
+ extendedInformation: `Dynamic SQL: Typically ABAP logic does not need dynamic SQL`,
40
44
  tags: [_irule_1.RuleTag.SingleFile, _irule_1.RuleTag.Security],
41
45
  };
42
46
  }
@@ -90,9 +94,29 @@ class DangerousStatement extends _abap_rule_1.ABAPRule {
90
94
  if (message) {
91
95
  issues.push(issue_1.Issue.atStatement(file, statementNode, this.getDescription(message), this.getMetadata().key, this.conf.severity));
92
96
  }
97
+ if (this.conf.dynamicSQL) {
98
+ message = this.findDynamicSQL(statementNode);
99
+ if (message) {
100
+ issues.push(issue_1.Issue.atStatement(file, statementNode, this.getDescription(message), this.getMetadata().key, this.conf.severity));
101
+ }
102
+ }
93
103
  }
94
104
  return issues;
95
105
  }
106
+ findDynamicSQL(statementNode) {
107
+ const statement = statementNode.get();
108
+ if (statement instanceof Statements.UpdateDatabase
109
+ || statement instanceof Statements.Select
110
+ || statement instanceof Statements.SelectLoop
111
+ || statement instanceof Statements.InsertDatabase
112
+ || statement instanceof Statements.ModifyDatabase
113
+ || statement instanceof Statements.DeleteDatabase) {
114
+ if (statementNode.findFirstExpression(Expressions.Dynamic)) {
115
+ return "Dynamic SQL";
116
+ }
117
+ }
118
+ return undefined;
119
+ }
96
120
  }
97
121
  exports.DangerousStatement = DangerousStatement;
98
122
  //# sourceMappingURL=dangerous_statement.js.map
@@ -123,7 +123,7 @@ POSIX REGEX: https://help.sap.com/doc/abapdocu_755_index_htm/7.55/en-US/index.ht
123
123
  this.conf = conf;
124
124
  }
125
125
  runParsed(file) {
126
- var _a, _b;
126
+ var _a, _b, _c;
127
127
  const issues = [];
128
128
  const statements = file.getStatements();
129
129
  let prev = undefined;
@@ -272,8 +272,7 @@ POSIX REGEX: https://help.sap.com/doc/abapdocu_755_index_htm/7.55/en-US/index.ht
272
272
  }
273
273
  if (configVersion >= version_1.Version.v756 && this.conf.regex) {
274
274
  if (sta instanceof Statements.Find || sta instanceof Statements.Replace) {
275
- const concat = staNode.concatTokens().toUpperCase();
276
- if (concat.includes("REGEX")) {
275
+ if ((_c = staNode.findFirstExpression(Expressions.FindType)) === null || _c === void 0 ? void 0 : _c.concatTokens().includes("REGEX")) {
277
276
  const issue = issue_1.Issue.atStatement(file, staNode, "REGEX obsolete, use PCRE", this.getMetadata().key, this.conf.severity);
278
277
  issues.push(issue);
279
278
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/core",
3
- "version": "2.79.30",
3
+ "version": "2.79.34",
4
4
  "description": "abaplint - Core API",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/abaplint.d.ts",
@@ -54,12 +54,12 @@
54
54
  },
55
55
  "homepage": "https://abaplint.org",
56
56
  "devDependencies": {
57
- "@microsoft/api-extractor": "^7.18.16",
57
+ "@microsoft/api-extractor": "^7.18.17",
58
58
  "@types/chai": "^4.2.22",
59
59
  "@types/mocha": "^9.0.0",
60
- "@types/node": "^16.11.0",
60
+ "@types/node": "^16.11.6",
61
61
  "chai": "^4.3.4",
62
- "eslint": "^8.0.1",
62
+ "eslint": "^8.1.0",
63
63
  "madge": "^5.0.1",
64
64
  "mocha": "^9.1.3",
65
65
  "c8": "^7.10.0",
@@ -68,7 +68,7 @@
68
68
  "typescript": "^4.4.4"
69
69
  },
70
70
  "dependencies": {
71
- "fast-xml-parser": "^3.20.3",
71
+ "fast-xml-parser": "^3.21.0",
72
72
  "json5": "^2.2.0",
73
73
  "vscode-languageserver-protocol": "^3.16.0",
74
74
  "vscode-languageserver-types": "^3.16.0"