@abaplint/core 2.100.6 → 2.101.0

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.
@@ -1265,6 +1265,7 @@ export declare class CurrentScope {
1265
1265
  private static addBuiltIn;
1266
1266
  private constructor();
1267
1267
  getVersion(): Version;
1268
+ getRegistry(): IRegistry;
1268
1269
  addType(type: TypedIdentifier | undefined): void;
1269
1270
  addTypeNamed(name: string, type: TypedIdentifier | undefined): void;
1270
1271
  addExtraLikeType(type: TypedIdentifier | undefined): void;
@@ -1278,6 +1279,7 @@ export declare class CurrentScope {
1278
1279
  addListPrefix(identifiers: readonly TypedIdentifier[], prefix: string): void;
1279
1280
  addList(identifiers: readonly TypedIdentifier[]): void;
1280
1281
  addReference(usage: Token | undefined, referencing: Identifier | undefined, type: ReferenceType | undefined, filename: string, extra?: IReferenceExtras): void;
1282
+ addSQLConversion(fieldName: string, message: string, token: Token): void;
1281
1283
  findFunctionModule(name: string | undefined): FunctionModuleDefinition | undefined;
1282
1284
  findObjectDefinition(name: string | undefined): IClassDefinition | IInterfaceDefinition | undefined;
1283
1285
  isBadiDef(name: string): boolean;
@@ -3547,6 +3549,11 @@ declare interface IScopeData {
3547
3549
  idefs: IInterfaceDefinition[];
3548
3550
  forms: IFormDefinition[];
3549
3551
  references: IReference[];
3552
+ sqlConversion: {
3553
+ fieldName: string;
3554
+ message: string;
3555
+ token: Token;
3556
+ }[];
3550
3557
  }
3551
3558
 
3552
3559
  declare interface IScopeIdentifier {
@@ -38,6 +38,9 @@ class CurrentScope {
38
38
  getVersion() {
39
39
  return this.reg.getConfig().getVersion();
40
40
  }
41
+ getRegistry() {
42
+ return this.reg;
43
+ }
41
44
  addType(type) {
42
45
  if (type === undefined) {
43
46
  return;
@@ -137,6 +140,10 @@ class CurrentScope {
137
140
  const position = new _identifier_1.Identifier(usage, filename);
138
141
  (_a = this.current) === null || _a === void 0 ? void 0 : _a.getData().references.push({ position, resolved: referencing, referenceType: type, extra });
139
142
  }
143
+ addSQLConversion(fieldName, message, token) {
144
+ var _a;
145
+ (_a = this.current) === null || _a === void 0 ? void 0 : _a.getData().sqlConversion.push({ fieldName, message, token });
146
+ }
140
147
  ///////////////////////////
141
148
  findFunctionModule(name) {
142
149
  if (name === undefined) {
@@ -8,7 +8,7 @@ class DatabaseTable {
8
8
  const name = token.getStr();
9
9
  if (name === "(") {
10
10
  // dynamic
11
- return;
11
+ return undefined;
12
12
  }
13
13
  const found = scope.getDDIC().lookupTableOrView2(name);
14
14
  if (found === undefined && scope.getDDIC().inErrorNamespace(name) === true) {
@@ -21,6 +21,7 @@ class DatabaseTable {
21
21
  scope.addReference(token, found.getIdentifier(), _reference_1.ReferenceType.TableReference, filename);
22
22
  scope.getDDICReferences().addUsing(scope.getParentObj(), { object: found, token: token, filename: filename });
23
23
  }
24
+ return found;
24
25
  }
25
26
  }
26
27
  exports.DatabaseTable = DatabaseTable;
@@ -6,17 +6,16 @@ const basic_1 = require("../../types/basic");
6
6
  const inline_data_1 = require("./inline_data");
7
7
  const target_1 = require("./target");
8
8
  const sql_from_1 = require("./sql_from");
9
- const source_1 = require("./source");
10
9
  const sql_for_all_entries_1 = require("./sql_for_all_entries");
11
10
  const _scope_type_1 = require("../_scope_type");
11
+ const sql_source_1 = require("./sql_source");
12
+ const sql_compare_1 = require("./sql_compare");
12
13
  class Select {
13
14
  runSyntax(node, scope, filename, skipImplicitInto = false) {
14
15
  var _a, _b;
15
16
  const token = node.getFirstToken();
16
17
  const from = node.findDirectExpression(Expressions.SQLFrom);
17
- if (from) {
18
- new sql_from_1.SQLFrom().runSyntax(from, scope, filename);
19
- }
18
+ const dbSources = from ? new sql_from_1.SQLFrom().runSyntax(from, scope, filename) : [];
20
19
  for (const inline of node.findAllExpressions(Expressions.InlineData)) {
21
20
  // todo, for now these are voided
22
21
  new inline_data_1.InlineData().runSyntax(inline, scope, filename, new basic_1.VoidType("SELECT_todo"));
@@ -42,11 +41,22 @@ class Select {
42
41
  }
43
42
  }
44
43
  }
45
- for (const s of node.findAllExpressions(Expressions.Source)) {
46
- new source_1.Source().runSyntax(s, scope, filename);
44
+ // OFFSET
45
+ for (const s of node.findDirectExpressions(Expressions.SQLSource)) {
46
+ new sql_source_1.SQLSource().runSyntax(s, scope, filename);
47
+ }
48
+ for (const up of node.findDirectExpressions(Expressions.SQLUpTo)) {
49
+ for (const s of up.findDirectExpressions(Expressions.SQLSource)) {
50
+ new sql_source_1.SQLSource().runSyntax(s, scope, filename);
51
+ }
52
+ }
53
+ for (const fae of node.findDirectExpressions(Expressions.SQLForAllEntries)) {
54
+ for (const s of fae.findDirectExpressions(Expressions.SQLSource)) {
55
+ new sql_source_1.SQLSource().runSyntax(s, scope, filename);
56
+ }
47
57
  }
48
- for (const s of node.findAllExpressions(Expressions.SimpleSource3)) {
49
- new source_1.Source().runSyntax(s, scope, filename);
58
+ for (const s of node.findAllExpressions(Expressions.SQLCompare)) {
59
+ new sql_compare_1.SQLCompare().runSyntax(s, scope, filename, dbSources);
50
60
  }
51
61
  if (scope.getType() === _scope_type_1.ScopeType.OpenSQL) {
52
62
  scope.pop(node.getLastToken().getEnd());
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SQLCompare = void 0;
4
+ const Expressions = require("../../2_statements/expressions");
5
+ const basic_1 = require("../../types/basic");
6
+ const sql_source_1 = require("./sql_source");
7
+ class SQLCompare {
8
+ runSyntax(node, scope, filename, tables) {
9
+ var _a;
10
+ let sourceType;
11
+ let token;
12
+ for (const s of node.findAllExpressions(Expressions.SQLSource)) {
13
+ token = s.getFirstToken();
14
+ sourceType = new sql_source_1.SQLSource().runSyntax(s, scope, filename);
15
+ }
16
+ const fieldName = (_a = node.findDirectExpression(Expressions.SQLFieldName)) === null || _a === void 0 ? void 0 : _a.concatTokens();
17
+ if (fieldName && sourceType && token) {
18
+ // check compatibility for rule sql_value_conversion
19
+ const targetType = this.findType(fieldName, tables, scope);
20
+ let message = "";
21
+ if (sourceType instanceof basic_1.IntegerType
22
+ && targetType instanceof basic_1.CharacterType) {
23
+ message = "Integer to CHAR conversion";
24
+ }
25
+ else if (sourceType instanceof basic_1.IntegerType
26
+ && targetType instanceof basic_1.NumericType) {
27
+ message = "Integer to NUMC conversion";
28
+ }
29
+ else if (sourceType instanceof basic_1.NumericType
30
+ && targetType instanceof basic_1.IntegerType) {
31
+ message = "NUMC to Integer conversion";
32
+ }
33
+ else if (sourceType instanceof basic_1.CharacterType
34
+ && targetType instanceof basic_1.IntegerType) {
35
+ message = "CHAR to Integer conversion";
36
+ }
37
+ else if (sourceType instanceof basic_1.CharacterType
38
+ && targetType instanceof basic_1.CharacterType
39
+ && sourceType.getLength() > targetType.getLength()) {
40
+ message = "Source field longer than database field, CHAR -> CHAR";
41
+ }
42
+ else if (sourceType instanceof basic_1.NumericType
43
+ && targetType instanceof basic_1.NumericType
44
+ && sourceType.getLength() > targetType.getLength()) {
45
+ message = "Source field longer than database field, NUMC -> NUMC";
46
+ }
47
+ if (message !== "") {
48
+ scope.addSQLConversion(fieldName, message, token);
49
+ }
50
+ }
51
+ }
52
+ findType(fieldName, tables, scope) {
53
+ for (const t of tables) {
54
+ const type = t === null || t === void 0 ? void 0 : t.parseType(scope.getRegistry());
55
+ if (type instanceof basic_1.StructureType) {
56
+ return type.getComponentByName(fieldName);
57
+ }
58
+ }
59
+ return undefined;
60
+ }
61
+ }
62
+ exports.SQLCompare = SQLCompare;
63
+ //# sourceMappingURL=sql_compare.js.map
@@ -6,6 +6,7 @@ const dynamic_1 = require("./dynamic");
6
6
  const database_table_1 = require("./database_table");
7
7
  class SQLFrom {
8
8
  runSyntax(node, scope, filename) {
9
+ const ret = [];
9
10
  const fromList = node.findAllExpressions(Expressions.SQLFromSource);
10
11
  for (const from of fromList) {
11
12
  for (const d of from.findAllExpressions(Expressions.Dynamic)) {
@@ -13,9 +14,10 @@ class SQLFrom {
13
14
  }
14
15
  const dbtab = from.findFirstExpression(Expressions.DatabaseTable);
15
16
  if (dbtab !== undefined) {
16
- new database_table_1.DatabaseTable().runSyntax(dbtab, scope, filename);
17
+ ret.push(new database_table_1.DatabaseTable().runSyntax(dbtab, scope, filename));
17
18
  }
18
19
  }
20
+ return ret;
19
21
  }
20
22
  }
21
23
  exports.SQLFrom = SQLFrom;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SQLSource = void 0;
4
+ const Expressions = require("../../2_statements/expressions");
5
+ const source_1 = require("./source");
6
+ class SQLSource {
7
+ runSyntax(node, scope, filename) {
8
+ for (const s of node.findAllExpressions(Expressions.Source)) {
9
+ return new source_1.Source().runSyntax(s, scope, filename);
10
+ }
11
+ for (const s of node.findAllExpressions(Expressions.SimpleSource3)) {
12
+ return new source_1.Source().runSyntax(s, scope, filename);
13
+ }
14
+ return undefined;
15
+ }
16
+ }
17
+ exports.SQLSource = SQLSource;
18
+ //# sourceMappingURL=sql_source.js.map
@@ -15,6 +15,7 @@ class ScopeData {
15
15
  extraLikeTypes: {},
16
16
  deferred: [],
17
17
  references: [],
18
+ sqlConversion: [],
18
19
  };
19
20
  }
20
21
  getData() {
@@ -65,7 +65,7 @@ class Registry {
65
65
  }
66
66
  static abaplintVersion() {
67
67
  // magic, see build script "version.sh"
68
- return "2.100.6";
68
+ return "2.101.0";
69
69
  }
70
70
  getDDICReferences() {
71
71
  return this.ddicReferences;
@@ -143,6 +143,7 @@ __exportStar(require("./smim_consistency"), exports);
143
143
  __exportStar(require("./space_before_colon"), exports);
144
144
  __exportStar(require("./space_before_dot"), exports);
145
145
  __exportStar(require("./sql_escape_host_variables"), exports);
146
+ __exportStar(require("./sql_value_conversion"), exports);
146
147
  __exportStar(require("./start_at_tab"), exports);
147
148
  __exportStar(require("./static_call_via_instance"), exports);
148
149
  __exportStar(require("./strict_sql"), exports);
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SQLValueConversion = exports.SQLValueConversionConf = void 0;
4
+ const issue_1 = require("../issue");
5
+ const _basic_rule_config_1 = require("./_basic_rule_config");
6
+ const objects_1 = require("../objects");
7
+ const syntax_1 = require("../abap/5_syntax/syntax");
8
+ const _abap_object_1 = require("../objects/_abap_object");
9
+ class SQLValueConversionConf extends _basic_rule_config_1.BasicRuleConfig {
10
+ }
11
+ exports.SQLValueConversionConf = SQLValueConversionConf;
12
+ class SQLValueConversion {
13
+ constructor() {
14
+ this.conf = new SQLValueConversionConf();
15
+ }
16
+ getMetadata() {
17
+ return {
18
+ key: "sql_value_conversion",
19
+ title: "Implicit SQL Value Conversion",
20
+ shortDescription: `Ensure types match when selecting from database`,
21
+ extendedInformation: `
22
+ * Integer to CHAR conversion
23
+ * Integer to NUMC conversion
24
+ * NUMC to Integer conversion
25
+ * CHAR to Integer conversion
26
+ * Source field longer than database field, CHAR -> CHAR
27
+ * Source field longer than database field, NUMC -> NUMC`,
28
+ tags: [],
29
+ };
30
+ }
31
+ getConfig() {
32
+ return this.conf;
33
+ }
34
+ setConfig(conf) {
35
+ this.conf = conf;
36
+ }
37
+ initialize(reg) {
38
+ this.reg = reg;
39
+ return this;
40
+ }
41
+ run(obj) {
42
+ if (!(obj instanceof _abap_object_1.ABAPObject) || obj instanceof objects_1.Interface) {
43
+ return [];
44
+ }
45
+ // messages defined in sql_compare.ts
46
+ const issues = this.traverse(new syntax_1.SyntaxLogic(this.reg, obj).run().spaghetti.getTop());
47
+ return issues;
48
+ }
49
+ traverse(node) {
50
+ const ret = [];
51
+ for (const r of node.getData().sqlConversion) {
52
+ const file = this.reg.getFileByName(node.getIdentifier().filename);
53
+ if (file === undefined) {
54
+ continue;
55
+ }
56
+ ret.push(issue_1.Issue.atToken(file, r.token, r.message, this.getMetadata().key, this.getConfig().severity));
57
+ }
58
+ for (const c of node.getChildren()) {
59
+ ret.push(...this.traverse(c));
60
+ }
61
+ return ret;
62
+ }
63
+ }
64
+ exports.SQLValueConversion = SQLValueConversion;
65
+ //# sourceMappingURL=sql_value_conversion.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/core",
3
- "version": "2.100.6",
3
+ "version": "2.101.0",
4
4
  "description": "abaplint - Core API",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/abaplint.d.ts",