@abaplint/transpiler 2.13.98 → 2.13.99

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.
@@ -15,6 +15,10 @@ export declare class Traversal {
15
15
  private readonly doOrWhileIndexBackups;
16
16
  private readonly statementsInsideLoop;
17
17
  private readonly enclosingDoOrWhile;
18
+ /** DATA, CONSTANTS and FIELD-SYMBOLS nested in blocks, already declared in front of the block */
19
+ private readonly declaredEarly;
20
+ private emittingEarly;
21
+ private blockDepth;
18
22
  readonly reg: abaplint.IRegistry;
19
23
  readonly options: ITranspilerOptions | undefined;
20
24
  constructor(spaghetti: abaplint.ISpaghettiScope, file: abaplint.ABAPFile, obj: abaplint.ABAPObject, reg: abaplint.IRegistry, options?: ITranspilerOptions);
@@ -106,6 +110,15 @@ export declare class Traversal {
106
110
  buildInternalName(name: string, def: abaplint.IClassDefinition | abaplint.IInterfaceDefinition | undefined): string;
107
111
  lookupClassOrInterface(name: string | undefined, token: abaplint.Token | undefined, directGlobal?: boolean): string;
108
112
  buildPrefix(): string;
113
+ /** In ABAP, DATA, CONSTANTS and FIELD-SYMBOLS are visible in the whole method/form/program, but a
114
+ * javascript "let" inside the block of an IF, LOOP, TRY etc. is not. So before each block on
115
+ * method/form/program level the declarations nested in it are output, in source order, and
116
+ * skipped inside the block. They then exist after the block even if the branch did not run,
117
+ * and are initialized once, also when the block is a loop */
118
+ private traverseProcedureLevel;
119
+ private declareNestedEarly;
120
+ private static isDeclaration;
121
+ private static findNestedDeclarations;
109
122
  protected traverseStructure(node: abaplint.Nodes.StructureNode): Chunk;
110
123
  protected traverseStatement(node: abaplint.Nodes.StatementNode): Chunk;
111
124
  protected traverseExpression(node: abaplint.Nodes.ExpressionNode): Chunk;
@@ -88,6 +88,10 @@ class Traversal {
88
88
  doOrWhileIndexBackups = new Map();
89
89
  statementsInsideLoop = new WeakSet();
90
90
  enclosingDoOrWhile = new WeakMap();
91
+ /** DATA, CONSTANTS and FIELD-SYMBOLS nested in blocks, already declared in front of the block */
92
+ declaredEarly = new WeakSet();
93
+ emittingEarly = false;
94
+ blockDepth = 0;
91
95
  reg;
92
96
  options;
93
97
  constructor(spaghetti, file, obj, reg, options) {
@@ -926,17 +930,15 @@ this.INTERNAL_ID = abap.internalIdCounter++;\n`;
926
930
  }
927
931
  else if (c.get() instanceof abaplint.Expressions.AttributeName
928
932
  && context instanceof abaplint.BasicTypes.ObjectReferenceType) {
929
- const id = context.getIdentifier();
930
- if (id instanceof abaplint.Types.ClassDefinition || id instanceof abaplint.Types.InterfaceDefinition) {
931
- const concat = c.concatTokens();
932
- if (concat.includes("~")) {
933
- const [iname, aname] = concat.split("~");
934
- const intf = this.findInterfaceDefinition(iname, scope);
935
- context = intf?.getAttributes().findByName(aname)?.getType();
936
- }
937
- else {
938
- context = id.getAttributes().findByName(concat)?.getType();
939
- }
933
+ const concat = c.concatTokens();
934
+ if (concat.includes("~")) {
935
+ const [iname, aname] = concat.split("~");
936
+ const intf = this.findInterfaceDefinition(iname, scope);
937
+ context = intf?.getAttributes().findByName(aname)?.getType();
938
+ }
939
+ else {
940
+ // Global references can carry an identifier rather than a class definition.
941
+ context = this.narrowContextAttribute(context, concat, scope);
940
942
  }
941
943
  }
942
944
  else if (c.get() instanceof abaplint.Expressions.AttributeName
@@ -950,7 +952,7 @@ this.INTERNAL_ID = abap.internalIdCounter++;\n`;
950
952
  return context;
951
953
  }
952
954
  isInsideLoop(node) {
953
- return this.statementsInsideLoop.has(node);
955
+ return this.statementsInsideLoop.has(node) && !this.declaredEarly.has(node);
954
956
  }
955
957
  isInsideDoOrWhile(node) {
956
958
  return this.findCurrentDoOrWhileIndexBackup(node) !== undefined;
@@ -1045,7 +1047,87 @@ this.INTERNAL_ID = abap.internalIdCounter++;\n`;
1045
1047
  return this.obj.getType() + "-" + this.obj.getName() + "-";
1046
1048
  }
1047
1049
  ////////////////////////////
1050
+ /** In ABAP, DATA, CONSTANTS and FIELD-SYMBOLS are visible in the whole method/form/program, but a
1051
+ * javascript "let" inside the block of an IF, LOOP, TRY etc. is not. So before each block on
1052
+ * method/form/program level the declarations nested in it are output, in source order, and
1053
+ * skipped inside the block. They then exist after the block even if the branch did not run,
1054
+ * and are initialized once, also when the block is a loop */
1055
+ traverseProcedureLevel(node) {
1056
+ const ret = new chunk_1.Chunk();
1057
+ for (const c of node.getChildren()) {
1058
+ if (c instanceof abaplint.Nodes.StructureNode && Traversal.isDeclaration(c) === false) {
1059
+ ret.appendChunk(this.declareNestedEarly(c));
1060
+ this.blockDepth++;
1061
+ try {
1062
+ ret.appendChunk(this.traverseStructure(c));
1063
+ }
1064
+ finally {
1065
+ this.blockDepth--;
1066
+ }
1067
+ }
1068
+ else {
1069
+ ret.appendChunk(this.traverse(c));
1070
+ }
1071
+ }
1072
+ return ret;
1073
+ }
1074
+ declareNestedEarly(block) {
1075
+ const found = [];
1076
+ Traversal.findNestedDeclarations(block, found);
1077
+ for (const node of found) {
1078
+ this.declaredEarly.add(node);
1079
+ if (node instanceof abaplint.Nodes.StructureNode) {
1080
+ for (const statement of node.findAllStatementNodes()) {
1081
+ this.declaredEarly.add(statement);
1082
+ }
1083
+ }
1084
+ }
1085
+ const ret = new chunk_1.Chunk();
1086
+ this.emittingEarly = true;
1087
+ try {
1088
+ for (const node of found) {
1089
+ ret.appendChunk(this.traverse(node));
1090
+ }
1091
+ }
1092
+ finally {
1093
+ this.emittingEarly = false;
1094
+ }
1095
+ return ret;
1096
+ }
1097
+ static isDeclaration(node) {
1098
+ const get = node.get();
1099
+ return get instanceof abaplint.Structures.Data
1100
+ || get instanceof abaplint.Structures.Constants
1101
+ || get instanceof abaplint.Structures.Types;
1102
+ }
1103
+ static findNestedDeclarations(node, found) {
1104
+ for (const c of node.getChildren()) {
1105
+ if (c instanceof abaplint.Nodes.StatementNode) {
1106
+ const get = c.get();
1107
+ if (get instanceof abaplint.Statements.Data
1108
+ || get instanceof abaplint.Statements.Constant
1109
+ || get instanceof abaplint.Statements.FieldSymbol) {
1110
+ found.push(c);
1111
+ }
1112
+ }
1113
+ else if (c instanceof abaplint.Nodes.StructureNode) {
1114
+ const get = c.get();
1115
+ if (get instanceof abaplint.Structures.Data || get instanceof abaplint.Structures.Constants) {
1116
+ found.push(c);
1117
+ }
1118
+ else {
1119
+ Traversal.findNestedDeclarations(c, found);
1120
+ }
1121
+ }
1122
+ }
1123
+ }
1048
1124
  traverseStructure(node) {
1125
+ if (this.declaredEarly.has(node) && this.emittingEarly === false) {
1126
+ return new chunk_1.Chunk();
1127
+ }
1128
+ else if (this.blockDepth === 0 && node.get() instanceof abaplint.Structures.Normal) {
1129
+ return this.traverseProcedureLevel(node);
1130
+ }
1049
1131
  const list = StructureTranspilers;
1050
1132
  const ret = new chunk_1.Chunk();
1051
1133
  const search = node.get().constructor.name + "Transpiler";
@@ -1068,6 +1150,9 @@ this.INTERNAL_ID = abap.internalIdCounter++;\n`;
1068
1150
  return ret;
1069
1151
  }
1070
1152
  traverseStatement(node) {
1153
+ if (this.declaredEarly.has(node) && this.emittingEarly === false) {
1154
+ return new chunk_1.Chunk();
1155
+ }
1071
1156
  const list = StatementTranspilers;
1072
1157
  const search = node.get().constructor.name + "Transpiler";
1073
1158
  if (list[search]) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/transpiler",
3
- "version": "2.13.98",
3
+ "version": "2.13.99",
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.120.66",
32
+ "@abaplint/core": "^2.120.68",
33
33
  "source-map": "^0.8.0"
34
34
  },
35
35
  "devDependencies": {