@abaplint/transpiler 2.13.63 → 2.13.65
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.
- package/build/src/chunk.d.ts +7 -6
- package/build/src/chunk.js +11 -8
- package/build/src/db/index.js +18 -8
- package/build/src/index.js +5 -3
- package/build/src/statements/assign.js +12 -3
- package/build/src/statements/at_pf.d.ts +7 -0
- package/build/src/statements/at_pf.js +11 -0
- package/build/src/statements/at_user_command.d.ts +7 -0
- package/build/src/statements/at_user_command.js +11 -0
- package/build/src/statements/call_selection_screen.d.ts +7 -0
- package/build/src/statements/call_selection_screen.js +11 -0
- package/build/src/statements/hide.d.ts +7 -0
- package/build/src/statements/hide.js +11 -0
- package/build/src/statements/index.d.ts +5 -0
- package/build/src/statements/index.js +5 -0
- package/build/src/statements/new_page.d.ts +7 -0
- package/build/src/statements/new_page.js +11 -0
- package/build/src/traversal.d.ts +6 -0
- package/build/src/traversal.js +63 -40
- package/package.json +2 -2
package/build/src/chunk.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import * as sourceMap from "source-map";
|
|
2
2
|
import * as abaplint from "@abaplint/core";
|
|
3
|
+
type SourceMapTraversal = {
|
|
4
|
+
getFilename(): string;
|
|
5
|
+
isSourceMapEnabled?(): boolean;
|
|
6
|
+
};
|
|
3
7
|
export declare class Chunk {
|
|
4
8
|
private raw;
|
|
5
9
|
private lineCount;
|
|
@@ -9,18 +13,14 @@ export declare class Chunk {
|
|
|
9
13
|
join(chunks: Chunk[], str?: string): Chunk;
|
|
10
14
|
appendChunk(append: Chunk): Chunk;
|
|
11
15
|
private originalPosition;
|
|
12
|
-
append(input: string, pos: abaplint.Position | abaplint.INode | abaplint.Token, traversal:
|
|
13
|
-
getFilename(): string;
|
|
14
|
-
}): Chunk;
|
|
16
|
+
append(input: string, pos: abaplint.Position | abaplint.INode | abaplint.Token, traversal: SourceMapTraversal): Chunk;
|
|
15
17
|
/**
|
|
16
18
|
* Baseline fallback so statements whose transpiler emitted no mappings still
|
|
17
19
|
* resolve to their ABAP source. Adds a single mapping from the start of this
|
|
18
20
|
* chunk (generated line 1, column 0) to `pos`. No-op if the chunk is empty or
|
|
19
21
|
* already carries mappings, so it never overrides finer-grained mappings.
|
|
20
22
|
*/
|
|
21
|
-
ensureStartMapping(pos: abaplint.Position | abaplint.INode | abaplint.Token, traversal:
|
|
22
|
-
getFilename(): string;
|
|
23
|
-
}): Chunk;
|
|
23
|
+
ensureStartMapping(pos: abaplint.Position | abaplint.INode | abaplint.Token, traversal: SourceMapTraversal): Chunk;
|
|
24
24
|
appendString(input: string): this;
|
|
25
25
|
stripLastNewline(): void;
|
|
26
26
|
getCode(): string;
|
|
@@ -41,3 +41,4 @@ export declare class Chunk {
|
|
|
41
41
|
};
|
|
42
42
|
}): string;
|
|
43
43
|
}
|
|
44
|
+
export {};
|
package/build/src/chunk.js
CHANGED
|
@@ -106,7 +106,7 @@ class Chunk {
|
|
|
106
106
|
if (input === "") {
|
|
107
107
|
return this;
|
|
108
108
|
}
|
|
109
|
-
if (pos && input !== "\n") {
|
|
109
|
+
if (pos && input !== "\n" && traversal.isSourceMapEnabled?.() !== false) {
|
|
110
110
|
this.mappings.push({
|
|
111
111
|
source: traversal.getFilename(),
|
|
112
112
|
generated: {
|
|
@@ -125,7 +125,7 @@ class Chunk {
|
|
|
125
125
|
* already carries mappings, so it never overrides finer-grained mappings.
|
|
126
126
|
*/
|
|
127
127
|
ensureStartMapping(pos, traversal) {
|
|
128
|
-
if (this.raw === "" || this.mappings.length > 0) {
|
|
128
|
+
if (this.raw === "" || this.mappings.length > 0 || traversal.isSourceMapEnabled?.() === false) {
|
|
129
129
|
return this;
|
|
130
130
|
}
|
|
131
131
|
this.mappings.push({
|
|
@@ -168,29 +168,32 @@ class Chunk {
|
|
|
168
168
|
if (ignoreSourceMap === true) {
|
|
169
169
|
this.mappings = [];
|
|
170
170
|
}
|
|
171
|
+
const indentationByLine = this.mappings.length > 0 ? [] : undefined;
|
|
171
172
|
for (const l of this.raw.split("\n")) {
|
|
172
173
|
if (l.startsWith("}")) {
|
|
173
174
|
i = i - 1;
|
|
174
175
|
}
|
|
175
176
|
// clamp so unbalanced braces never produce a negative indent/shift
|
|
176
177
|
const indent = i > 0 ? i * 2 : 0;
|
|
178
|
+
if (indentationByLine !== undefined) {
|
|
179
|
+
indentationByLine[line] = indent;
|
|
180
|
+
}
|
|
177
181
|
if (indent > 0) {
|
|
178
182
|
output.push(" ".repeat(indent) + l);
|
|
179
183
|
}
|
|
180
184
|
else {
|
|
181
185
|
output.push(l);
|
|
182
186
|
}
|
|
183
|
-
// fix maps: shift columns by the indentation actually applied to this line
|
|
184
|
-
for (const m of this.mappings) {
|
|
185
|
-
if (m.generated.line === line) {
|
|
186
|
-
m.generated.column += indent;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
187
|
if (l.endsWith(" {")) {
|
|
190
188
|
i = i + 1;
|
|
191
189
|
}
|
|
192
190
|
line++;
|
|
193
191
|
}
|
|
192
|
+
// Shift every mapping once. The previous line-major implementation
|
|
193
|
+
// inspected every mapping for every generated line (O(lines * mappings)).
|
|
194
|
+
for (const m of this.mappings) {
|
|
195
|
+
m.generated.column += indentationByLine?.[m.generated.line] || 0;
|
|
196
|
+
}
|
|
194
197
|
this.raw = output.join("\n");
|
|
195
198
|
// line structure is unchanged, but the last line may have been indented
|
|
196
199
|
this.lastLineLength = output[output.length - 1].length;
|
package/build/src/db/index.js
CHANGED
|
@@ -83,39 +83,49 @@ class DatabaseSetup {
|
|
|
83
83
|
// note: avoid hitting maximum statement size by splitting into multiple statements
|
|
84
84
|
const insert = [];
|
|
85
85
|
const populateTables = new populate_tables_1.PopulateTables(this.reg);
|
|
86
|
+
const add = (statement) => {
|
|
87
|
+
if (statement.length > 0) {
|
|
88
|
+
insert.push(statement);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
const addAll = (statements) => {
|
|
92
|
+
for (const statement of statements) {
|
|
93
|
+
add(statement);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
86
96
|
// INSERT data
|
|
87
97
|
for (const obj of this.reg.getObjects()) {
|
|
88
98
|
if (options?.populateTables?.tadir !== false) {
|
|
89
|
-
|
|
99
|
+
add(populateTables.insertTADIR(obj));
|
|
90
100
|
}
|
|
91
101
|
if (obj instanceof abaplint.Objects.MessageClass) {
|
|
92
|
-
|
|
102
|
+
addAll(populateTables.insertT100(obj));
|
|
93
103
|
}
|
|
94
104
|
else if (options?.populateTables?.wwwparams !== false
|
|
95
105
|
&& obj instanceof abaplint.Objects.WebMIME) {
|
|
96
|
-
|
|
106
|
+
addAll(populateTables.insertWWWPARAMS(obj));
|
|
97
107
|
}
|
|
98
108
|
else if (obj instanceof abaplint.Objects.Class
|
|
99
109
|
|| obj instanceof abaplint.Objects.Interface
|
|
100
110
|
|| obj instanceof abaplint.Objects.Program) {
|
|
101
111
|
if (options?.populateTables?.reposrc !== false) {
|
|
102
|
-
|
|
112
|
+
add(populateTables.insertREPOSRC(obj));
|
|
103
113
|
}
|
|
104
114
|
if ((obj instanceof abaplint.Objects.Class || obj instanceof abaplint.Objects.Interface)
|
|
105
115
|
&& options?.populateTables?.seosubco !== false) {
|
|
106
|
-
|
|
116
|
+
addAll(populateTables.insertSEOSUBCO(obj));
|
|
107
117
|
}
|
|
108
118
|
if ((obj instanceof abaplint.Objects.Class || obj instanceof abaplint.Objects.Interface)
|
|
109
119
|
&& options?.populateTables?.seosubcodf !== false) {
|
|
110
|
-
|
|
120
|
+
addAll(populateTables.insertSEOSUBCODF(obj));
|
|
111
121
|
}
|
|
112
122
|
if ((obj instanceof abaplint.Objects.Class || obj instanceof abaplint.Objects.Interface)
|
|
113
123
|
&& options?.populateTables?.seosubcotx !== false) {
|
|
114
|
-
|
|
124
|
+
addAll(populateTables.insertSEOSUBCOTX(obj));
|
|
115
125
|
}
|
|
116
126
|
}
|
|
117
127
|
}
|
|
118
|
-
|
|
128
|
+
add(populateTables.insertT000());
|
|
119
129
|
return insert;
|
|
120
130
|
}
|
|
121
131
|
}
|
package/build/src/index.js
CHANGED
|
@@ -72,11 +72,13 @@ class Transpiler {
|
|
|
72
72
|
// workaround for web/webpack
|
|
73
73
|
async runRaw(files) {
|
|
74
74
|
const memory = files.map(f => new abaplint.MemoryFile(f.filename, f.contents));
|
|
75
|
-
const reg = new abaplint.Registry().addFiles(memory)
|
|
76
|
-
return
|
|
75
|
+
const reg = new abaplint.Registry().addFiles(memory);
|
|
76
|
+
return this.run(reg);
|
|
77
77
|
}
|
|
78
78
|
async run(reg, progress) {
|
|
79
|
-
|
|
79
|
+
// Validation installs the transpiler configuration and findIssues() parses
|
|
80
|
+
// dirty registries. Parsing before that would be wasted because setConfig()
|
|
81
|
+
// marks every registry object dirty again.
|
|
80
82
|
this.validate(reg);
|
|
81
83
|
const dbSetup = new db_1.DatabaseSetup(reg).run(this.options);
|
|
82
84
|
this.plugin?.amendDatabaseSetup?.(dbSetup, reg, this.options || {});
|
|
@@ -97,7 +97,14 @@ class AssignTranspiler {
|
|
|
97
97
|
}
|
|
98
98
|
else {
|
|
99
99
|
let dynamicName = "";
|
|
100
|
-
|
|
100
|
+
const first = assignSource?.getFirstChild();
|
|
101
|
+
// dynamicSource below already contains the first source expression.
|
|
102
|
+
// Keep only the dynamic suffix in dynamicName, otherwise structure
|
|
103
|
+
// components in that expression are resolved a second time at runtime.
|
|
104
|
+
const dynamicNameChildren = first?.get() instanceof abaplint.Expressions.Source
|
|
105
|
+
? assignSource?.getChildren().slice(1)
|
|
106
|
+
: assignSource?.getChildren();
|
|
107
|
+
for (const c of dynamicNameChildren || []) {
|
|
101
108
|
if (c instanceof abaplint.Nodes.ExpressionNode
|
|
102
109
|
&& c.get() instanceof abaplint.Expressions.Dynamic
|
|
103
110
|
&& c.findFirstExpression(abaplint.Expressions.ConstantString)) {
|
|
@@ -118,7 +125,10 @@ class AssignTranspiler {
|
|
|
118
125
|
continue;
|
|
119
126
|
}
|
|
120
127
|
else if (c.concatTokens() === "=>" || c.concatTokens() === "->") {
|
|
121
|
-
dynamicName
|
|
128
|
+
if (dynamicName !== "") {
|
|
129
|
+
dynamicName += " + ";
|
|
130
|
+
}
|
|
131
|
+
dynamicName += "'" + c.concatTokens() + "'";
|
|
122
132
|
}
|
|
123
133
|
else {
|
|
124
134
|
if (dynamicName !== "") {
|
|
@@ -129,7 +139,6 @@ class AssignTranspiler {
|
|
|
129
139
|
}
|
|
130
140
|
options.push(`dynamicName: ` + dynamicName);
|
|
131
141
|
// dynamicSource is the first part of the dynamic part
|
|
132
|
-
const first = assignSource?.getFirstChild();
|
|
133
142
|
if (first?.get() instanceof abaplint.Expressions.Dynamic && first instanceof abaplint.Nodes.ExpressionNode) {
|
|
134
143
|
const firstFirst = first.getChildren()[1];
|
|
135
144
|
if (firstFirst?.get() instanceof abaplint.Expressions.Constant) {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as abaplint from "@abaplint/core";
|
|
2
|
+
import { IStatementTranspiler } from "./_statement_transpiler";
|
|
3
|
+
import { Traversal } from "../traversal";
|
|
4
|
+
import { Chunk } from "../chunk";
|
|
5
|
+
export declare class AtPFTranspiler implements IStatementTranspiler {
|
|
6
|
+
transpile(_node: abaplint.Nodes.StatementNode, _traversal: Traversal): Chunk;
|
|
7
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AtPFTranspiler = void 0;
|
|
4
|
+
const chunk_1 = require("../chunk");
|
|
5
|
+
class AtPFTranspiler {
|
|
6
|
+
transpile(_node, _traversal) {
|
|
7
|
+
return new chunk_1.Chunk(`throw new Error("AT PFnn, not supported, transpiler");`);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.AtPFTranspiler = AtPFTranspiler;
|
|
11
|
+
//# sourceMappingURL=at_pf.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as abaplint from "@abaplint/core";
|
|
2
|
+
import { IStatementTranspiler } from "./_statement_transpiler";
|
|
3
|
+
import { Traversal } from "../traversal";
|
|
4
|
+
import { Chunk } from "../chunk";
|
|
5
|
+
export declare class AtUserCommandTranspiler implements IStatementTranspiler {
|
|
6
|
+
transpile(_node: abaplint.Nodes.StatementNode, _traversal: Traversal): Chunk;
|
|
7
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AtUserCommandTranspiler = void 0;
|
|
4
|
+
const chunk_1 = require("../chunk");
|
|
5
|
+
class AtUserCommandTranspiler {
|
|
6
|
+
transpile(_node, _traversal) {
|
|
7
|
+
return new chunk_1.Chunk(`throw new Error("AT USER-COMMAND, not supported, transpiler");`);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.AtUserCommandTranspiler = AtUserCommandTranspiler;
|
|
11
|
+
//# sourceMappingURL=at_user_command.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as abaplint from "@abaplint/core";
|
|
2
|
+
import { IStatementTranspiler } from "./_statement_transpiler";
|
|
3
|
+
import { Traversal } from "../traversal";
|
|
4
|
+
import { Chunk } from "../chunk";
|
|
5
|
+
export declare class CallSelectionScreenTranspiler implements IStatementTranspiler {
|
|
6
|
+
transpile(_node: abaplint.Nodes.StatementNode, _traversal: Traversal): Chunk;
|
|
7
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CallSelectionScreenTranspiler = void 0;
|
|
4
|
+
const chunk_1 = require("../chunk");
|
|
5
|
+
class CallSelectionScreenTranspiler {
|
|
6
|
+
transpile(_node, _traversal) {
|
|
7
|
+
return new chunk_1.Chunk(`throw new Error("CALL SELECTION-SCREEN, not supported, transpiler");`);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.CallSelectionScreenTranspiler = CallSelectionScreenTranspiler;
|
|
11
|
+
//# sourceMappingURL=call_selection_screen.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as abaplint from "@abaplint/core";
|
|
2
|
+
import { IStatementTranspiler } from "./_statement_transpiler";
|
|
3
|
+
import { Traversal } from "../traversal";
|
|
4
|
+
import { Chunk } from "../chunk";
|
|
5
|
+
export declare class HideTranspiler implements IStatementTranspiler {
|
|
6
|
+
transpile(_node: abaplint.Nodes.StatementNode, _traversal: Traversal): Chunk;
|
|
7
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HideTranspiler = void 0;
|
|
4
|
+
const chunk_1 = require("../chunk");
|
|
5
|
+
class HideTranspiler {
|
|
6
|
+
transpile(_node, _traversal) {
|
|
7
|
+
return new chunk_1.Chunk(`throw new Error("HIDE, not supported, transpiler");`);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.HideTranspiler = HideTranspiler;
|
|
11
|
+
//# sourceMappingURL=hide.js.map
|
|
@@ -2,14 +2,17 @@ export * from "./add";
|
|
|
2
2
|
export * from "./append";
|
|
3
3
|
export * from "./assert";
|
|
4
4
|
export * from "./assign";
|
|
5
|
+
export * from "./at_pf";
|
|
5
6
|
export * from "./at_selection_screen";
|
|
6
7
|
export * from "./at";
|
|
8
|
+
export * from "./at_user_command";
|
|
7
9
|
export * from "./authority_check";
|
|
8
10
|
export * from "./break_id";
|
|
9
11
|
export * from "./break";
|
|
10
12
|
export * from "./call_function";
|
|
11
13
|
export * from "./call_kernel";
|
|
12
14
|
export * from "./call_screen";
|
|
15
|
+
export * from "./call_selection_screen";
|
|
13
16
|
export * from "./call_transaction";
|
|
14
17
|
export * from "./call_transformation";
|
|
15
18
|
export * from "./call";
|
|
@@ -77,6 +80,7 @@ export * from "./get_parameter";
|
|
|
77
80
|
export * from "./get_reference";
|
|
78
81
|
export * from "./get_run_time";
|
|
79
82
|
export * from "./get_time";
|
|
83
|
+
export * from "./hide";
|
|
80
84
|
export * from "./if";
|
|
81
85
|
export * from "./import";
|
|
82
86
|
export * from "./include";
|
|
@@ -98,6 +102,7 @@ export * from "./modify_internal";
|
|
|
98
102
|
export * from "./modify_screen";
|
|
99
103
|
export * from "./move_corresponding";
|
|
100
104
|
export * from "./move";
|
|
105
|
+
export * from "./new_page";
|
|
101
106
|
export * from "./open_cursor";
|
|
102
107
|
export * from "./open_dataset";
|
|
103
108
|
export * from "./overlay";
|
|
@@ -18,14 +18,17 @@ __exportStar(require("./add"), exports);
|
|
|
18
18
|
__exportStar(require("./append"), exports);
|
|
19
19
|
__exportStar(require("./assert"), exports);
|
|
20
20
|
__exportStar(require("./assign"), exports);
|
|
21
|
+
__exportStar(require("./at_pf"), exports);
|
|
21
22
|
__exportStar(require("./at_selection_screen"), exports);
|
|
22
23
|
__exportStar(require("./at"), exports);
|
|
24
|
+
__exportStar(require("./at_user_command"), exports);
|
|
23
25
|
__exportStar(require("./authority_check"), exports);
|
|
24
26
|
__exportStar(require("./break_id"), exports);
|
|
25
27
|
__exportStar(require("./break"), exports);
|
|
26
28
|
__exportStar(require("./call_function"), exports);
|
|
27
29
|
__exportStar(require("./call_kernel"), exports);
|
|
28
30
|
__exportStar(require("./call_screen"), exports);
|
|
31
|
+
__exportStar(require("./call_selection_screen"), exports);
|
|
29
32
|
__exportStar(require("./call_transaction"), exports);
|
|
30
33
|
__exportStar(require("./call_transformation"), exports);
|
|
31
34
|
__exportStar(require("./call"), exports);
|
|
@@ -93,6 +96,7 @@ __exportStar(require("./get_parameter"), exports);
|
|
|
93
96
|
__exportStar(require("./get_reference"), exports);
|
|
94
97
|
__exportStar(require("./get_run_time"), exports);
|
|
95
98
|
__exportStar(require("./get_time"), exports);
|
|
99
|
+
__exportStar(require("./hide"), exports);
|
|
96
100
|
__exportStar(require("./if"), exports);
|
|
97
101
|
__exportStar(require("./import"), exports);
|
|
98
102
|
__exportStar(require("./include"), exports);
|
|
@@ -114,6 +118,7 @@ __exportStar(require("./modify_internal"), exports);
|
|
|
114
118
|
__exportStar(require("./modify_screen"), exports);
|
|
115
119
|
__exportStar(require("./move_corresponding"), exports);
|
|
116
120
|
__exportStar(require("./move"), exports);
|
|
121
|
+
__exportStar(require("./new_page"), exports);
|
|
117
122
|
__exportStar(require("./open_cursor"), exports);
|
|
118
123
|
__exportStar(require("./open_dataset"), exports);
|
|
119
124
|
__exportStar(require("./overlay"), exports);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as abaplint from "@abaplint/core";
|
|
2
|
+
import { IStatementTranspiler } from "./_statement_transpiler";
|
|
3
|
+
import { Traversal } from "../traversal";
|
|
4
|
+
import { Chunk } from "../chunk";
|
|
5
|
+
export declare class NewPageTranspiler implements IStatementTranspiler {
|
|
6
|
+
transpile(_node: abaplint.Nodes.StatementNode, _traversal: Traversal): Chunk;
|
|
7
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NewPageTranspiler = void 0;
|
|
4
|
+
const chunk_1 = require("../chunk");
|
|
5
|
+
class NewPageTranspiler {
|
|
6
|
+
transpile(_node, _traversal) {
|
|
7
|
+
return new chunk_1.Chunk(`throw new Error("NEW-PAGE, not supported, transpiler");`);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.NewPageTranspiler = NewPageTranspiler;
|
|
11
|
+
//# sourceMappingURL=new_page.js.map
|
package/build/src/traversal.d.ts
CHANGED
|
@@ -7,9 +7,14 @@ export declare class Traversal {
|
|
|
7
7
|
private readonly obj;
|
|
8
8
|
private sqlInferredType;
|
|
9
9
|
private readonly doOrWhileIndexBackups;
|
|
10
|
+
private readonly statementsInsideLoop;
|
|
11
|
+
private readonly enclosingDoOrWhile;
|
|
10
12
|
readonly reg: abaplint.IRegistry;
|
|
11
13
|
readonly options: ITranspilerOptions | undefined;
|
|
12
14
|
constructor(spaghetti: abaplint.ISpaghettiScope, file: abaplint.ABAPFile, obj: abaplint.ABAPObject, reg: abaplint.IRegistry, options?: ITranspilerOptions);
|
|
15
|
+
/** Build file-level control-flow context once instead of rescanning all
|
|
16
|
+
* preceding statements for every DATA, CHECK, EXIT, and RETURN. */
|
|
17
|
+
private buildStatementContext;
|
|
13
18
|
static escapeNamespace(name: string | undefined): string | undefined;
|
|
14
19
|
/** the self reference "me", it is a FieldChain in eg. MethodCallChain and a SourceField in eg. MethodSource */
|
|
15
20
|
static isMe(node: abaplint.Nodes.ExpressionNode | abaplint.Nodes.TokenNode | abaplint.Nodes.StructureNode): boolean;
|
|
@@ -19,6 +24,7 @@ export declare class Traversal {
|
|
|
19
24
|
getFilename(): string;
|
|
20
25
|
getFile(): abaplint.ABAPFile;
|
|
21
26
|
getSpaghetti(): abaplint.ISpaghettiScope;
|
|
27
|
+
isSourceMapEnabled(): boolean;
|
|
22
28
|
/** finds a statement in the _current_ file given a position */
|
|
23
29
|
findStatementInFile(pos: abaplint.Position): abaplint.Nodes.StatementNode | undefined;
|
|
24
30
|
private scopeCache;
|
package/build/src/traversal.js
CHANGED
|
@@ -48,6 +48,8 @@ class Traversal {
|
|
|
48
48
|
obj;
|
|
49
49
|
sqlInferredType;
|
|
50
50
|
doOrWhileIndexBackups = new Map();
|
|
51
|
+
statementsInsideLoop = new WeakSet();
|
|
52
|
+
enclosingDoOrWhile = new WeakMap();
|
|
51
53
|
reg;
|
|
52
54
|
options;
|
|
53
55
|
constructor(spaghetti, file, obj, reg, options) {
|
|
@@ -56,6 +58,43 @@ class Traversal {
|
|
|
56
58
|
this.obj = obj;
|
|
57
59
|
this.reg = reg;
|
|
58
60
|
this.options = options;
|
|
61
|
+
this.buildStatementContext();
|
|
62
|
+
}
|
|
63
|
+
/** Build file-level control-flow context once instead of rescanning all
|
|
64
|
+
* preceding statements for every DATA, CHECK, EXIT, and RETURN. */
|
|
65
|
+
buildStatementContext() {
|
|
66
|
+
const loopStack = [];
|
|
67
|
+
const doOrWhileStack = [];
|
|
68
|
+
for (const statement of this.file.getStatements()) {
|
|
69
|
+
const get = statement.get();
|
|
70
|
+
if (get instanceof abaplint.Statements.Loop
|
|
71
|
+
|| get instanceof abaplint.Statements.While
|
|
72
|
+
|| get instanceof abaplint.Statements.SelectLoop
|
|
73
|
+
|| get instanceof abaplint.Statements.Do) {
|
|
74
|
+
loopStack.push(statement);
|
|
75
|
+
}
|
|
76
|
+
else if (get instanceof abaplint.Statements.EndLoop
|
|
77
|
+
|| get instanceof abaplint.Statements.EndWhile
|
|
78
|
+
|| get instanceof abaplint.Statements.EndSelect
|
|
79
|
+
|| get instanceof abaplint.Statements.EndDo) {
|
|
80
|
+
loopStack.pop();
|
|
81
|
+
}
|
|
82
|
+
if (loopStack.length > 0) {
|
|
83
|
+
this.statementsInsideLoop.add(statement);
|
|
84
|
+
}
|
|
85
|
+
if (get instanceof abaplint.Statements.While
|
|
86
|
+
|| get instanceof abaplint.Statements.Do) {
|
|
87
|
+
doOrWhileStack.push(statement);
|
|
88
|
+
}
|
|
89
|
+
else if (get instanceof abaplint.Statements.EndWhile
|
|
90
|
+
|| get instanceof abaplint.Statements.EndDo) {
|
|
91
|
+
doOrWhileStack.pop();
|
|
92
|
+
}
|
|
93
|
+
const enclosing = doOrWhileStack[doOrWhileStack.length - 1];
|
|
94
|
+
if (enclosing !== undefined) {
|
|
95
|
+
this.enclosingDoOrWhile.set(statement, enclosing);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
59
98
|
}
|
|
60
99
|
static escapeNamespace(name) {
|
|
61
100
|
return name?.replace(/\//g, "$");
|
|
@@ -102,6 +141,9 @@ class Traversal {
|
|
|
102
141
|
getSpaghetti() {
|
|
103
142
|
return this.spaghetti;
|
|
104
143
|
}
|
|
144
|
+
isSourceMapEnabled() {
|
|
145
|
+
return this.options?.ignoreSourceMap !== true;
|
|
146
|
+
}
|
|
105
147
|
/** finds a statement in the _current_ file given a position */
|
|
106
148
|
findStatementInFile(pos) {
|
|
107
149
|
for (const s of this.file.getStatements()) {
|
|
@@ -564,9 +606,16 @@ class Traversal {
|
|
|
564
606
|
return ret;
|
|
565
607
|
}
|
|
566
608
|
buildFriendsAccess(def, hasSuperClass) {
|
|
567
|
-
let ret = "
|
|
609
|
+
let ret = "";
|
|
568
610
|
if (hasSuperClass === true) {
|
|
569
|
-
|
|
611
|
+
// A subclass instance can be held through a superclass reference. In
|
|
612
|
+
// that case friend access must still find private members declared by
|
|
613
|
+
// the superclass.
|
|
614
|
+
ret += "this.FRIENDS_ACCESS_INSTANCE = Object.create(sup.FRIENDS_ACCESS_INSTANCE || null);\n";
|
|
615
|
+
ret += `this.FRIENDS_ACCESS_INSTANCE["SUPER"] = sup.FRIENDS_ACCESS_INSTANCE;\n`;
|
|
616
|
+
}
|
|
617
|
+
else {
|
|
618
|
+
ret += "this.FRIENDS_ACCESS_INSTANCE = {\n";
|
|
570
619
|
}
|
|
571
620
|
for (const method of def.getMethodDefinitions()?.getAll() || []) {
|
|
572
621
|
const name = method.getName().toLowerCase();
|
|
@@ -579,9 +628,16 @@ class Traversal {
|
|
|
579
628
|
}
|
|
580
629
|
const methodName = privateHash + Traversal.escapeNamespace(name.replace("~", "$"));
|
|
581
630
|
// NOTE: currently all are needed in the unit test setup
|
|
582
|
-
|
|
631
|
+
if (hasSuperClass === true) {
|
|
632
|
+
ret += `this.FRIENDS_ACCESS_INSTANCE["${name.replace("~", "$")}"] = this.${methodName}.bind(this);\n`;
|
|
633
|
+
}
|
|
634
|
+
else {
|
|
635
|
+
ret += `"${name.replace("~", "$")}": this.${methodName}.bind(this),\n`;
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
if (hasSuperClass === false) {
|
|
639
|
+
ret += "};\n";
|
|
583
640
|
}
|
|
584
|
-
ret += "};\n";
|
|
585
641
|
return ret;
|
|
586
642
|
}
|
|
587
643
|
buildConstructorContents(scope, def) {
|
|
@@ -820,26 +876,7 @@ this.INTERNAL_ID = abap.internalIdCounter++;\n`;
|
|
|
820
876
|
return context;
|
|
821
877
|
}
|
|
822
878
|
isInsideLoop(node) {
|
|
823
|
-
|
|
824
|
-
for (const statement of this.getFile().getStatements()) {
|
|
825
|
-
const get = statement.get();
|
|
826
|
-
if (get instanceof abaplint.Statements.Loop
|
|
827
|
-
|| get instanceof abaplint.Statements.While
|
|
828
|
-
|| get instanceof abaplint.Statements.SelectLoop
|
|
829
|
-
|| get instanceof abaplint.Statements.Do) {
|
|
830
|
-
stack.push(statement);
|
|
831
|
-
}
|
|
832
|
-
else if (get instanceof abaplint.Statements.EndLoop
|
|
833
|
-
|| get instanceof abaplint.Statements.EndWhile
|
|
834
|
-
|| get instanceof abaplint.Statements.EndSelect
|
|
835
|
-
|| get instanceof abaplint.Statements.EndDo) {
|
|
836
|
-
stack.pop();
|
|
837
|
-
}
|
|
838
|
-
if (statement === node) {
|
|
839
|
-
break;
|
|
840
|
-
}
|
|
841
|
-
}
|
|
842
|
-
return stack.length > 0;
|
|
879
|
+
return this.statementsInsideLoop.has(node);
|
|
843
880
|
}
|
|
844
881
|
isInsideDoOrWhile(node) {
|
|
845
882
|
return this.findCurrentDoOrWhileIndexBackup(node) !== undefined;
|
|
@@ -848,22 +885,8 @@ this.INTERNAL_ID = abap.internalIdCounter++;\n`;
|
|
|
848
885
|
this.doOrWhileIndexBackups.set(node, name);
|
|
849
886
|
}
|
|
850
887
|
findCurrentDoOrWhileIndexBackup(node) {
|
|
851
|
-
const
|
|
852
|
-
|
|
853
|
-
const get = statement.get();
|
|
854
|
-
if (get instanceof abaplint.Statements.While
|
|
855
|
-
|| get instanceof abaplint.Statements.Do) {
|
|
856
|
-
stack.push(this.doOrWhileIndexBackups.get(statement));
|
|
857
|
-
}
|
|
858
|
-
else if (get instanceof abaplint.Statements.EndWhile
|
|
859
|
-
|| get instanceof abaplint.Statements.EndDo) {
|
|
860
|
-
stack.pop();
|
|
861
|
-
}
|
|
862
|
-
if (statement === node) {
|
|
863
|
-
break;
|
|
864
|
-
}
|
|
865
|
-
}
|
|
866
|
-
return stack[stack.length - 1];
|
|
888
|
+
const enclosing = this.enclosingDoOrWhile.get(node);
|
|
889
|
+
return enclosing === undefined ? undefined : this.doOrWhileIndexBackups.get(enclosing);
|
|
867
890
|
}
|
|
868
891
|
registerClassOrInterface(def) {
|
|
869
892
|
if (def === undefined) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abaplint/transpiler",
|
|
3
|
-
"version": "2.13.
|
|
3
|
+
"version": "2.13.65",
|
|
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.
|
|
32
|
+
"@abaplint/core": "^2.120.42",
|
|
33
33
|
"source-map": "^0.7.6"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|