@abaplint/transpiler 2.7.0 → 2.7.2

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.
@@ -4,6 +4,12 @@ exports.DatabaseSetup = void 0;
4
4
  /* eslint-disable max-len */
5
5
  const abaplint = require("@abaplint/core");
6
6
  const sqlite_database_schema_1 = require("./sqlite_database_schema");
7
+ const pg_database_schema_1 = require("./pg_database_schema");
8
+ /////////////////////////
9
+ // NOTES
10
+ /////////////////////////
11
+ // Postgres is case sensitive, so all column names should be lower case
12
+ // Sqlite escapes field names with single qoute, postgres with double
7
13
  class DatabaseSetup {
8
14
  constructor(reg) {
9
15
  this.reg = reg;
@@ -13,7 +19,7 @@ class DatabaseSetup {
13
19
  schemas: {
14
20
  sqlite: new sqlite_database_schema_1.SQLiteDatabaseSchema(this.reg).run(),
15
21
  hdb: ["todo"],
16
- pg: ["todo"],
22
+ pg: new pg_database_schema_1.PGDatabaseSchema(this.reg).run(),
17
23
  },
18
24
  insert: this.buildInsert(options),
19
25
  };
@@ -57,7 +63,7 @@ class DatabaseSetup {
57
63
  const type = tabl.parseType(this.reg);
58
64
  if (type instanceof abaplint.BasicTypes.StructureType && type.getComponents().length >= 3) {
59
65
  // todo, this should take the client number from the settings
60
- return `INSERT INTO t000 ('MANDT', 'CCCATEGORY', 'CCNOCLIIND') VALUES ('123', '', '');`;
66
+ return `INSERT INTO t000 ('mandt', 'cccategory', 'ccnocliind') VALUES ('123', '', '');`;
61
67
  }
62
68
  else {
63
69
  return "";
@@ -71,7 +77,7 @@ class DatabaseSetup {
71
77
  }
72
78
  let ret = "";
73
79
  for (const m of msag.getMessages()) {
74
- ret += `INSERT INTO t100 ('SPRSL', 'ARBGB', 'MSGNR', 'TEXT') VALUES ('E', '${msag.getName().padEnd(20, " ")}', '${m.getNumber()}', '${this.escape(m.getMessage().padEnd(73, " "))}');\n`;
80
+ ret += `INSERT INTO t100 ("sprsl", "arbgb", "msgnr", "text") VALUES ('E', '${msag.getName().padEnd(20, " ")}', '${m.getNumber()}', '${this.escape(m.getMessage().padEnd(73, " "))}');\n`;
75
81
  }
76
82
  return ret;
77
83
  }
@@ -0,0 +1,9 @@
1
+ import * as abaplint from "@abaplint/core";
2
+ export declare class PGDatabaseSchema {
3
+ private readonly reg;
4
+ constructor(reg: abaplint.IRegistry);
5
+ run(): string[];
6
+ private buildVIEW;
7
+ private buildTABL;
8
+ private toType;
9
+ }
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PGDatabaseSchema = void 0;
4
+ const abaplint = require("@abaplint/core");
5
+ class PGDatabaseSchema {
6
+ constructor(reg) {
7
+ this.reg = reg;
8
+ }
9
+ run() {
10
+ const statements = [];
11
+ // CREATE TABLEs
12
+ for (const obj of this.reg.getObjects()) {
13
+ if (obj instanceof abaplint.Objects.Table
14
+ && obj.getTableCategory() === abaplint.Objects.TableCategory.Transparent) {
15
+ statements.push(this.buildTABL(obj).trim());
16
+ }
17
+ }
18
+ // CREATE VIEWs after TABLEs
19
+ // todo: what if the view is based on another view?
20
+ for (const obj of this.reg.getObjects()) {
21
+ if (obj instanceof abaplint.Objects.View) {
22
+ statements.push(this.buildVIEW(obj).trim());
23
+ }
24
+ }
25
+ return statements;
26
+ }
27
+ //////////////////
28
+ // https://www.sqlite.org/lang_createview.html
29
+ buildVIEW(view) {
30
+ const fields = view.getFields();
31
+ let firstTabname = "";
32
+ const columns = fields === null || fields === void 0 ? void 0 : fields.map((f) => {
33
+ firstTabname = "'" + f.TABNAME.toLowerCase() + "'";
34
+ return firstTabname + "." + f.FIELDNAME.toLowerCase() + " AS " + f.VIEWFIELD.toLowerCase();
35
+ }).join(", ");
36
+ let from = "";
37
+ let previous = "";
38
+ for (const j of view.getJoin() || []) {
39
+ if (previous === "") {
40
+ from += "'" + j.LTAB.toLowerCase() + "' INNER JOIN '" + j.RTAB.toLowerCase() + "' ON '" + j.LTAB.toLowerCase() + "'." + j.LFIELD.toLowerCase() + " = '" + j.RTAB.toLowerCase() + "'." + j.RFIELD.toLowerCase();
41
+ }
42
+ else if (previous === j.LTAB + "," + j.RTAB) {
43
+ from += " AND '" + j.LTAB.toLowerCase() + "'." + j.LFIELD.toLowerCase() + " = '" + j.RTAB.toLowerCase() + "'." + j.RFIELD.toLowerCase();
44
+ }
45
+ else {
46
+ from += " INNER JOIN '" + j.RTAB.toLowerCase() + "' ON '" + j.LTAB.toLowerCase() + "'." + j.LFIELD.toLowerCase() + " = '" + j.RTAB.toLowerCase() + "'." + j.RFIELD.toLowerCase();
47
+ }
48
+ previous = j.LTAB + "," + j.RTAB;
49
+ }
50
+ from = from.trim();
51
+ if (from === "") {
52
+ from = firstTabname;
53
+ }
54
+ return `CREATE VIEW '${view.getName().toLowerCase()}' AS SELECT ${columns} FROM ${from};\n`;
55
+ }
56
+ buildTABL(tabl) {
57
+ const type = tabl.parseType(this.reg);
58
+ if (!(type instanceof abaplint.BasicTypes.StructureType)) {
59
+ return "";
60
+ }
61
+ const fields = [];
62
+ const fieldsRaw = [];
63
+ for (const field of type.getComponents()) {
64
+ if (field.type instanceof abaplint.BasicTypes.StructureType) {
65
+ // is a GROUP NAME
66
+ continue;
67
+ }
68
+ fieldsRaw.push(field.name.toLowerCase());
69
+ fields.push("\"" + field.name.toLowerCase() + "\" " + this.toType(field.type, field.name, tabl.getName()));
70
+ }
71
+ // assumption: all transparent tables have primary keys
72
+ // add single quotes to field names to allow for keywords as field names
73
+ const key = ", PRIMARY KEY(" + tabl.listKeys(this.reg)
74
+ .filter(e => fieldsRaw.includes(e.toLowerCase()))
75
+ .map(e => "\"" + e.toLowerCase() + "\"").join(",") + ")";
76
+ return `CREATE TABLE "${tabl.getName().toLowerCase()}" (${fields.join(", ")}${key});\n`;
77
+ }
78
+ toType(type, fieldname, errorInfo) {
79
+ if (type instanceof abaplint.BasicTypes.CharacterType) {
80
+ return `NCHAR(${type.getLength()})`;
81
+ }
82
+ else if (type instanceof abaplint.BasicTypes.TimeType) {
83
+ return `NCHAR(6)`;
84
+ }
85
+ else if (type instanceof abaplint.BasicTypes.DateType) {
86
+ return `NCHAR(8)`;
87
+ }
88
+ else if (type instanceof abaplint.BasicTypes.NumericType) {
89
+ // it will be fine, the runtime representation of numc is also text
90
+ return `NCHAR(${type.getLength()})`;
91
+ }
92
+ else if (type instanceof abaplint.BasicTypes.StringType) {
93
+ return `TEXT`;
94
+ }
95
+ else if (type instanceof abaplint.BasicTypes.XStringType) {
96
+ // it will be fine, the runtime representation of xstring is also text
97
+ return `TEXT`;
98
+ }
99
+ else if (type instanceof abaplint.BasicTypes.HexType) {
100
+ return `NCHAR(${type.getLength() * 2})`;
101
+ }
102
+ else if (type instanceof abaplint.BasicTypes.IntegerType) {
103
+ return `INT`;
104
+ }
105
+ else if (type instanceof abaplint.BasicTypes.FloatType
106
+ || type instanceof abaplint.BasicTypes.FloatingPointType) {
107
+ return `REAL`;
108
+ }
109
+ else if (type instanceof abaplint.BasicTypes.PackedType) {
110
+ return `DECIMAL(${type.getLength()},${type.getDecimals()})`;
111
+ }
112
+ else if (type instanceof abaplint.BasicTypes.VoidType) {
113
+ throw `Type of ${errorInfo}-${fieldname} is VoidType(${type.getVoided()}), make sure the type is known, enable strict syntax checking`;
114
+ }
115
+ else {
116
+ throw "database_setup: " + errorInfo + "-" + fieldname + ", todo toType handle: " + type.constructor.name;
117
+ }
118
+ }
119
+ }
120
+ exports.PGDatabaseSchema = PGDatabaseSchema;
121
+ //# sourceMappingURL=pg_database_schema.js.map
@@ -1,7 +1,7 @@
1
1
  import * as abaplint from "@abaplint/core";
2
2
  import { config } from "./validation";
3
3
  import { IFile, IOutput, IProgress, ITranspilerOptions, IOutputFile } from "./types";
4
- export { config, ITranspilerOptions, IFile, IProgress, IOutputFile };
4
+ export { config, ITranspilerOptions, IFile, IProgress, IOutputFile, IOutput };
5
5
  export declare class Transpiler {
6
6
  private readonly options;
7
7
  constructor(options?: ITranspilerOptions);
@@ -23,7 +23,8 @@ class ClassImplementationTranspiler {
23
23
  static INTERNAL_TYPE = 'CLAS';
24
24
  static INTERNAL_NAME = '${traversal.buildInternalName(token.getStr(), def)}';
25
25
  static IMPLEMENTED_INTERFACES = [${this.findImplementedByClass(traversal, def, scope).map(e => `"` + e.toUpperCase() + `"`).join(",")}];
26
- static ATTRIBUTES = {${traversal.buildAttributes(def, scope).join(",\n")}};`, node, traversal);
26
+ static ATTRIBUTES = {${traversal.buildAttributes(def, scope).join(",\n")}};
27
+ static METHODS = {${traversal.buildMethods(def, scope).join(",\n")}};`, node, traversal);
27
28
  }
28
29
  findImplementedInterface(traversal, def, scope) {
29
30
  if (def === undefined || scope === undefined) {
@@ -20,6 +20,7 @@ class InterfaceTranspiler {
20
20
  ret += `class ${name} {\n`;
21
21
  ret += `static INTERNAL_TYPE = 'INTF';\n`;
22
22
  ret += `static ATTRIBUTES = {${traversal.buildAttributes(def, scope).join(",\n")}};\n`;
23
+ ret += `static METHODS = {${traversal.buildMethods(def, scope).join(",\n")}};\n`;
23
24
  }
24
25
  else if (c instanceof abaplint.Nodes.StatementNode && c.get() instanceof abaplint.Statements.EndInterface) {
25
26
  ret += "}\n";
@@ -26,9 +26,11 @@ class SelectTranspiler {
26
26
  const packageSize = (_b = node.findFirstExpression(abaplint.Expressions.SelectLoop)) === null || _b === void 0 ? void 0 : _b.findExpressionAfterToken("SIZE");
27
27
  if (packageSize) {
28
28
  const getSize = new expressions_1.SQLSourceTranspiler().transpile(packageSize, traversal).getCode() + ".get()";
29
- ret.appendString(`if (${targetName}.array().length > ${getSize}) { throw new Error("PACKAGE SIZED loop larger than package size not supported"); };\n`);
30
- ret.appendString(`abap.statements.append({source: ${targetName}, target: ${intoName}, lines: true});\n`);
31
- ret.appendString(`{\n`);
29
+ ret.appendString(`if (${targetName}.array().length > ${getSize}) {
30
+ throw new Error("PACKAGE SIZED loop larger than package size not supported");
31
+ };
32
+ abap.statements.append({source: ${targetName}, target: ${intoName}, lines: true});
33
+ {\n`);
32
34
  }
33
35
  else if (concat.includes(" INTO CORRESPONDING FIELDS OF ")) {
34
36
  ret.appendString(`\nfor (const ${loopName} of ${targetName}.array()) {\n`);
@@ -24,6 +24,8 @@ export declare class Traversal {
24
24
  private isClassAttribute;
25
25
  prefixAndName(t: abaplint.Token, filename?: string): string;
26
26
  private isStaticClassAttribute;
27
+ buildMethods(def: abaplint.IClassDefinition | abaplint.IInterfaceDefinition | undefined, _scope: abaplint.ISpaghettiScopeNode | undefined): string[];
28
+ private mapVisibility;
27
29
  buildAttributes(def: abaplint.IClassDefinition | abaplint.IInterfaceDefinition | undefined, scope: abaplint.ISpaghettiScopeNode | undefined, prefix?: string): string[];
28
30
  isBuiltinMethod(token: abaplint.Token): boolean;
29
31
  findMethodReference(token: abaplint.Token, scope: ISpaghettiScopeNode | undefined): undefined | {
@@ -169,6 +169,32 @@ class Traversal {
169
169
  }
170
170
  return undefined;
171
171
  }
172
+ buildMethods(def, _scope) {
173
+ const methods = [];
174
+ if (def === undefined) {
175
+ return methods;
176
+ }
177
+ for (const m of def.getMethodDefinitions().getAll()) {
178
+ const parameters = [];
179
+ for (const p of m.getParameters().getAll()) {
180
+ const type = new transpile_types_1.TranspileTypes().toType(p.getType());
181
+ const optional = m.getParameters().getOptional().includes(p.getName()) ? "X" : " ";
182
+ parameters.push(`"${p.getName().toUpperCase()}": {"type": () => {return ${type};}, "is_optional": "${optional}"}`);
183
+ }
184
+ methods.push(`"${m.getName().toUpperCase()}": {"visibility": "${this.mapVisibility(m.getVisibility())}", "parameters": {${parameters.join(", ")}}}`);
185
+ }
186
+ return methods;
187
+ }
188
+ mapVisibility(vis) {
189
+ switch (vis) {
190
+ case abaplint.Visibility.Private:
191
+ return "I";
192
+ case abaplint.Visibility.Protected:
193
+ return "O";
194
+ default:
195
+ return "U";
196
+ }
197
+ }
172
198
  buildAttributes(def, scope, prefix = "") {
173
199
  var _a, _b;
174
200
  const attr = [];
@@ -177,17 +203,7 @@ class Traversal {
177
203
  }
178
204
  for (const a of ((_a = def.getAttributes()) === null || _a === void 0 ? void 0 : _a.getAll()) || []) {
179
205
  const type = new transpile_types_1.TranspileTypes().toType(a.getType());
180
- let runtime = "";
181
- switch (a.getVisibility()) {
182
- case abaplint.Visibility.Private:
183
- runtime = "I";
184
- break;
185
- case abaplint.Visibility.Protected:
186
- runtime = "O";
187
- break;
188
- default:
189
- runtime = "U";
190
- }
206
+ const runtime = this.mapVisibility(a.getVisibility());
191
207
  const isClass = a.getMeta().includes("static" /* abaplint.IdentifierMeta.Static */) ? "X" : " ";
192
208
  attr.push(`"${prefix + a.getName().toUpperCase()}": {"type": () => {return ${type};}, "visibility": "${runtime}", "is_constant": " ", "is_class": "${isClass}"}`);
193
209
  }
@@ -340,10 +356,12 @@ class Traversal {
340
356
  ret += "this.me = new abap.types.ABAPObject();\n";
341
357
  ret += "this.me.set(this);\n";
342
358
  for (const a of ((_a = def.getAttributes()) === null || _a === void 0 ? void 0 : _a.getAll()) || []) {
359
+ const escaped = Traversal.escapeNamespace(a.getName().toLowerCase());
343
360
  if (a.getMeta().includes("static" /* abaplint.IdentifierMeta.Static */) === true) {
361
+ ret += "this." + escaped + " = " + cName + "." + escaped + ";\n";
344
362
  continue;
345
363
  }
346
- const name = "this." + Traversal.escapeNamespace(a.getName().toLowerCase());
364
+ const name = "this." + escaped;
347
365
  ret += name + " = " + new transpile_types_1.TranspileTypes().toType(a.getType()) + ";\n";
348
366
  ret += this.setValues(a, name);
349
367
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/transpiler",
3
- "version": "2.7.0",
3
+ "version": "2.7.2",
4
4
  "description": "Transpiler",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/src/index.d.ts",
@@ -29,7 +29,7 @@
29
29
  "author": "abaplint",
30
30
  "license": "MIT",
31
31
  "dependencies": {
32
- "@abaplint/core": "^2.100.2",
32
+ "@abaplint/core": "^2.100.3",
33
33
  "source-map": "^0.7.4"
34
34
  },
35
35
  "devDependencies": {