@backtickjs/compiler 0.0.0-stage → 0.1.1
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/LICENSE +21 -0
- package/README.md +25 -2
- package/dist/CodeInformation.d.ts +8 -0
- package/dist/CodeInformation.js +2 -0
- package/dist/CodeInformation.js.map +1 -0
- package/dist/SourceRange.d.ts +4 -0
- package/dist/SourceRange.js +2 -0
- package/dist/SourceRange.js.map +1 -0
- package/dist/buildMappings.d.ts +10 -0
- package/dist/buildMappings.js +21 -0
- package/dist/buildMappings.js.map +1 -0
- package/dist/compileModule.d.ts +25 -0
- package/dist/compileModule.js +78 -0
- package/dist/compileModule.js.map +1 -0
- package/dist/compileScript.d.ts +24 -0
- package/dist/compileScript.js +66 -0
- package/dist/compileScript.js.map +1 -0
- package/dist/diagnostics.d.ts +8 -0
- package/dist/diagnostics.js +2 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/emitScript.d.ts +52 -0
- package/dist/emitScript.js +201 -0
- package/dist/emitScript.js.map +1 -0
- package/dist/emitScripts.d.ts +10 -0
- package/dist/emitScripts.js +23 -0
- package/dist/emitScripts.js.map +1 -0
- package/dist/flattenScripts.d.ts +2 -0
- package/dist/flattenScripts.js +10 -0
- package/dist/flattenScripts.js.map +1 -0
- package/dist/hashText.d.ts +1 -0
- package/dist/hashText.js +18 -0
- package/dist/hashText.js.map +1 -0
- package/dist/hostElements.d.ts +3 -0
- package/dist/hostElements.js +28 -0
- package/dist/hostElements.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/isComponentTag.d.ts +1 -0
- package/dist/isComponentTag.js +15 -0
- package/dist/isComponentTag.js.map +1 -0
- package/dist/nodeFactory.d.ts +3 -0
- package/dist/nodeFactory.js +5 -0
- package/dist/nodeFactory.js.map +1 -0
- package/dist/parseFile.d.ts +34 -0
- package/dist/parseFile.js +200 -0
- package/dist/parseFile.js.map +1 -0
- package/dist/printVirtualCode.d.ts +9 -0
- package/dist/printVirtualCode.js +52 -0
- package/dist/printVirtualCode.js.map +1 -0
- package/dist/resolveBindings.d.ts +76 -0
- package/dist/resolveBindings.js +240 -0
- package/dist/resolveBindings.js.map +1 -0
- package/dist/rewriteFile.d.ts +12 -0
- package/dist/rewriteFile.js +22 -0
- package/dist/rewriteFile.js.map +1 -0
- package/dist/rewriteScript.d.ts +27 -0
- package/dist/rewriteScript.js +268 -0
- package/dist/rewriteScript.js.map +1 -0
- package/dist/segmentsToString.d.ts +9 -0
- package/dist/segmentsToString.js +4 -0
- package/dist/segmentsToString.js.map +1 -0
- package/dist/tagRoot.d.ts +2 -0
- package/dist/tagRoot.js +10 -0
- package/dist/tagRoot.js.map +1 -0
- package/dist/transform.d.ts +17 -0
- package/dist/transform.js +61 -0
- package/dist/transform.js.map +1 -0
- package/dist/transpile.d.ts +27 -0
- package/dist/transpile.js +41 -0
- package/dist/transpile.js.map +1 -0
- package/dist/unmangle.d.ts +2 -0
- package/dist/unmangle.js +9 -0
- package/dist/unmangle.js.map +1 -0
- package/dist/virtualScript.d.ts +22 -0
- package/dist/virtualScript.js +305 -0
- package/dist/virtualScript.js.map +1 -0
- package/dist/virtualize.d.ts +8 -0
- package/dist/virtualize.js +10 -0
- package/dist/virtualize.js.map +1 -0
- package/package.json +58 -3
- package/src/CodeInformation.ts +14 -0
- package/src/SourceRange.ts +4 -0
- package/src/buildMappings.ts +31 -0
- package/src/compileModule.ts +132 -0
- package/src/compileScript.ts +97 -0
- package/src/diagnostics.ts +9 -0
- package/src/emitScript.ts +297 -0
- package/src/emitScripts.ts +39 -0
- package/src/flattenScripts.ts +13 -0
- package/src/hashText.ts +17 -0
- package/src/hostElements.ts +34 -0
- package/src/index.ts +20 -0
- package/src/isComponentTag.ts +15 -0
- package/src/nodeFactory.ts +18 -0
- package/src/parseFile.ts +331 -0
- package/src/printVirtualCode.ts +93 -0
- package/src/resolveBindings.ts +417 -0
- package/src/rewriteFile.ts +52 -0
- package/src/rewriteScript.ts +413 -0
- package/src/segmentsToString.ts +16 -0
- package/src/tagRoot.ts +14 -0
- package/src/transform.ts +96 -0
- package/src/transpile.ts +49 -0
- package/src/unmangle.ts +10 -0
- package/src/virtualScript.ts +355 -0
- package/src/virtualize.ts +29 -0
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
import type ts from "typescript";
|
|
2
|
+
import type { CodeInformation } from "./CodeInformation.js";
|
|
3
|
+
import type { ClientScript, Splice } from "./parseFile.js";
|
|
4
|
+
import type { BindingResolution } from "./resolveBindings.js";
|
|
5
|
+
import type { Segment } from "./segmentsToString.js";
|
|
6
|
+
import { tagRoot } from "./tagRoot.js";
|
|
7
|
+
import { mangle } from "./unmangle.js";
|
|
8
|
+
|
|
9
|
+
// What the editor reads through a wrapper the virtual code adds: nothing.
|
|
10
|
+
const WRAPPER: CodeInformation = { semantic: false, navigation: false };
|
|
11
|
+
// What it reads through a name the virtual code adds over a span of the
|
|
12
|
+
// script: only what is reported there. Hover and navigation stay with the
|
|
13
|
+
// script's own names inside it.
|
|
14
|
+
const REPORTED: CodeInformation = { semantic: false, navigation: false };
|
|
15
|
+
// A host tag's name, written as a value: everything but its color, which stays
|
|
16
|
+
// the tag's, as JSX colors it.
|
|
17
|
+
const TAG_NAME: CodeInformation = {
|
|
18
|
+
semantic: { shouldHighlight: () => false },
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A script as the typechecker reads it: its own text, as written, wrapped as
|
|
23
|
+
* `cs.lift((() => …)())`, edited only where a name means something else on
|
|
24
|
+
* the client.
|
|
25
|
+
*
|
|
26
|
+
* - its own binding, renamed (`x` to `__cs_x`), so it can't hide a host binding
|
|
27
|
+
* a splice names; a shorthand keeps its property name (`x: __cs_x`)
|
|
28
|
+
* - a name nothing declares, read as the client's global (`cs.globalThis.x`)
|
|
29
|
+
* - a splice, as the host value the client is handed: `$x` as
|
|
30
|
+
* `cs.splice((x))`, `${…}` as `cs.splice(…)` around the host code
|
|
31
|
+
* - a splice written as a tag, `<$Card>`, as JSX on a name the host value is
|
|
32
|
+
* handed to: `(($Card) => <$Card …>…</$Card>)(cs.splice((Card)))`, and
|
|
33
|
+
* `(void (Card), …)` where it closes, for the closing tag's name
|
|
34
|
+
*
|
|
35
|
+
* Everything else, types included, is TypeScript's to read as written. Each
|
|
36
|
+
* piece maps back to the text it came from; what the wrapper adds maps to no
|
|
37
|
+
* editor feature.
|
|
38
|
+
*/
|
|
39
|
+
export function virtualScript(
|
|
40
|
+
ts: typeof import("typescript"),
|
|
41
|
+
script: ClientScript,
|
|
42
|
+
bindings: BindingResolution,
|
|
43
|
+
awaits: boolean,
|
|
44
|
+
renderSplice: (splice: Splice) => Segment[],
|
|
45
|
+
): Segment[] {
|
|
46
|
+
const file = script.fileWithPlaceholders;
|
|
47
|
+
const text = script.textWithPlaceholders;
|
|
48
|
+
const out: Segment[] = [];
|
|
49
|
+
|
|
50
|
+
const verbatim = (from: number, to: number): void => {
|
|
51
|
+
if (to > from) {
|
|
52
|
+
out.push([
|
|
53
|
+
text.slice(from, to),
|
|
54
|
+
undefined,
|
|
55
|
+
script.toSourceOffset(from),
|
|
56
|
+
to - from,
|
|
57
|
+
]);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
const mapped = (
|
|
61
|
+
written: string,
|
|
62
|
+
node: ts.Node,
|
|
63
|
+
data?: CodeInformation,
|
|
64
|
+
): void => {
|
|
65
|
+
const { start, end } = script.toSourceRange(node);
|
|
66
|
+
out.push(
|
|
67
|
+
data === undefined
|
|
68
|
+
? [written, undefined, start, end - start]
|
|
69
|
+
: [written, undefined, start, end - start, data],
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
// Text the virtual code adds, reported at `at` in the host file if at all.
|
|
73
|
+
const added = (written: string, at?: number, data = WRAPPER): void => {
|
|
74
|
+
out.push(at === undefined ? written : [written, undefined, at, 0, data]);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const emit = (node: ts.Node, from = node.getStart(file)): void => {
|
|
78
|
+
if (ts.isIdentifier(node)) {
|
|
79
|
+
identifier(node);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if (
|
|
83
|
+
(ts.isJsxElement(node) || ts.isJsxSelfClosingElement(node)) &&
|
|
84
|
+
isHostTag(node)
|
|
85
|
+
) {
|
|
86
|
+
hostTag(node);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const children = node.getChildren(file);
|
|
90
|
+
if (children.length === 0) {
|
|
91
|
+
verbatim(from, node.getEnd());
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
let at = from;
|
|
95
|
+
for (const child of children) {
|
|
96
|
+
if (child.getEnd() <= at) {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
verbatim(at, child.getStart(file));
|
|
100
|
+
emit(child);
|
|
101
|
+
at = child.getEnd();
|
|
102
|
+
}
|
|
103
|
+
verbatim(at, node.getEnd());
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const identifier = (node: ts.Identifier): void => {
|
|
107
|
+
if (inTypePosition(ts, node)) {
|
|
108
|
+
verbatim(node.getStart(file), node.getEnd());
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const splice = script.splices[node.text];
|
|
112
|
+
if (splice !== undefined && splice.refs.includes(node)) {
|
|
113
|
+
// Parenthesized whole, so what it stands in reads it as one value: in
|
|
114
|
+
// `new $Animated.Value(0)`, `new` takes `$Animated.Value`, not the call.
|
|
115
|
+
const range = script.toSourceRange(node);
|
|
116
|
+
if (splice.kind === "braced") {
|
|
117
|
+
added("(cs.splice(", splice.expression.getStart(script.sourceFile));
|
|
118
|
+
out.push(...renderSplice(splice));
|
|
119
|
+
added("))", splice.expression.getEnd());
|
|
120
|
+
} else {
|
|
121
|
+
// The name parenthesized too, as 1-char padding: `(count)` against
|
|
122
|
+
// `$count` starts the name where it follows the sigil, so a
|
|
123
|
+
// completion's replacement span round-trips to the bare name.
|
|
124
|
+
added("(cs.splice(", range.start);
|
|
125
|
+
mapped(`(${splice.expression.text})`, node);
|
|
126
|
+
added("))", range.end);
|
|
127
|
+
}
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const parent = node.parent;
|
|
131
|
+
const shorthand =
|
|
132
|
+
(ts.isShorthandPropertyAssignment(parent) && parent.name === node) ||
|
|
133
|
+
(ts.isBindingElement(parent) &&
|
|
134
|
+
parent.name === node &&
|
|
135
|
+
parent.propertyName === undefined &&
|
|
136
|
+
parent.dotDotDotToken === undefined &&
|
|
137
|
+
ts.isObjectBindingPattern(parent.parent));
|
|
138
|
+
if (bindings.has(node)) {
|
|
139
|
+
if (shorthand) {
|
|
140
|
+
mapped(node.text, node);
|
|
141
|
+
added(": ");
|
|
142
|
+
}
|
|
143
|
+
mapped(mangle(node.text), node);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
if (node.text !== "undefined" && isReference(ts, node)) {
|
|
147
|
+
if (shorthand) {
|
|
148
|
+
mapped(node.text, node);
|
|
149
|
+
added(": ");
|
|
150
|
+
}
|
|
151
|
+
added("cs.globalThis.");
|
|
152
|
+
mapped(node.text, node);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
verbatim(node.getStart(file), node.getEnd());
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
// A tag that splices a host value, `<$Card>`, which the client is handed
|
|
159
|
+
// as a component.
|
|
160
|
+
const isHostTag = (
|
|
161
|
+
node: ts.JsxElement | ts.JsxSelfClosingElement,
|
|
162
|
+
): boolean => {
|
|
163
|
+
const root = tagRoot(
|
|
164
|
+
ts,
|
|
165
|
+
ts.isJsxElement(node) ? node.openingElement.tagName : node.tagName,
|
|
166
|
+
);
|
|
167
|
+
return (
|
|
168
|
+
root !== undefined &&
|
|
169
|
+
script.splices[root.text]?.refs.includes(root) === true
|
|
170
|
+
);
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
// A host tag is checked as JSX, as a tag is anywhere: on a parameter the
|
|
174
|
+
// host value is handed to, `(($Card) => <$Card …>…</$Card>)(cs.splice((Card)))`.
|
|
175
|
+
// JSX then checks it however the component is declared (a class, generic,
|
|
176
|
+
// overloaded) and allows what the framework allows on any tag (React's
|
|
177
|
+
// `key`). Its props and children are written as they were. The parameter
|
|
178
|
+
// takes the tag's written name, which a script can't otherwise bind, so an
|
|
179
|
+
// error about the tag names it as written, and is reported there; the name
|
|
180
|
+
// itself is read through `(Card)`, mapped to it, so definition, rename and
|
|
181
|
+
// references reach the host binding. Where the tag closes, `void (Card)`
|
|
182
|
+
// beside it does the same for the closing tag's name.
|
|
183
|
+
const hostTag = (node: ts.JsxElement | ts.JsxSelfClosingElement): void => {
|
|
184
|
+
const opening = ts.isJsxElement(node) ? node.openingElement : node;
|
|
185
|
+
const tagName = opening.tagName;
|
|
186
|
+
// What the tag starts with, `$Card`, or `$Animated` in `<$Animated.View>`:
|
|
187
|
+
// the splice. The rest, `.View`, is written as it was.
|
|
188
|
+
const root = tagRoot(ts, tagName)!;
|
|
189
|
+
const tag = script.toSourceRange(root);
|
|
190
|
+
// The binding's name, parenthesized over its `$` as an unbraced splice is.
|
|
191
|
+
const name = `(${(script.splices[root.text]!.expression as ts.Identifier).text})`;
|
|
192
|
+
// Where JSX stands, an expression is written in braces: a child of an
|
|
193
|
+
// element or fragment, or an attribute's value.
|
|
194
|
+
const parent = node.parent;
|
|
195
|
+
const braced =
|
|
196
|
+
ts.isJsxAttribute(parent) ||
|
|
197
|
+
ts.isJsxElement(parent) ||
|
|
198
|
+
ts.isJsxFragment(parent);
|
|
199
|
+
if (braced) {
|
|
200
|
+
added("{");
|
|
201
|
+
}
|
|
202
|
+
const closing = ts.isJsxElement(node)
|
|
203
|
+
? tagRoot(ts, node.closingElement.tagName)!
|
|
204
|
+
: undefined;
|
|
205
|
+
if (closing !== undefined) {
|
|
206
|
+
added("(void ");
|
|
207
|
+
mapped(name, closing, TAG_NAME);
|
|
208
|
+
added(", ");
|
|
209
|
+
}
|
|
210
|
+
added(`((${root.text}) => <`);
|
|
211
|
+
mapped(root.text, root, REPORTED);
|
|
212
|
+
verbatim(root.getEnd(), tagName.getEnd());
|
|
213
|
+
// Its attributes and the opening's end, as written. What stands between
|
|
214
|
+
// the name and the first attribute maps to nothing: the end of the name is
|
|
215
|
+
// the name's, not the attribute's.
|
|
216
|
+
let at = tagName.getEnd();
|
|
217
|
+
for (const [index, attribute] of opening.attributes.properties.entries()) {
|
|
218
|
+
if (index === 0) {
|
|
219
|
+
added(text.slice(at, attribute.getStart(file)));
|
|
220
|
+
} else {
|
|
221
|
+
verbatim(at, attribute.getStart(file));
|
|
222
|
+
}
|
|
223
|
+
emit(attribute);
|
|
224
|
+
at = attribute.getEnd();
|
|
225
|
+
}
|
|
226
|
+
if (opening.attributes.properties.length === 0) {
|
|
227
|
+
added(text.slice(at, opening.getEnd()));
|
|
228
|
+
} else {
|
|
229
|
+
verbatim(at, opening.getEnd());
|
|
230
|
+
}
|
|
231
|
+
if (ts.isJsxElement(node)) {
|
|
232
|
+
at = opening.getEnd();
|
|
233
|
+
for (const child of node.children) {
|
|
234
|
+
verbatim(at, child.getStart(file));
|
|
235
|
+
emit(child);
|
|
236
|
+
at = child.getEnd();
|
|
237
|
+
}
|
|
238
|
+
verbatim(at, node.closingElement.getStart(file));
|
|
239
|
+
added("</");
|
|
240
|
+
mapped(root.text, closing!, REPORTED);
|
|
241
|
+
verbatim(closing!.getEnd(), node.closingElement.tagName.getEnd());
|
|
242
|
+
added(">");
|
|
243
|
+
}
|
|
244
|
+
added(")(cs.splice(", tag.start);
|
|
245
|
+
mapped(name, tagName, TAG_NAME);
|
|
246
|
+
added("))", tag.end);
|
|
247
|
+
if (ts.isJsxElement(node)) {
|
|
248
|
+
added(")");
|
|
249
|
+
}
|
|
250
|
+
if (braced) {
|
|
251
|
+
added("}");
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
// The wrapper the script is checked in, mapped to what it stands for: its
|
|
256
|
+
// opening to `cs\``, its close to the closing backtick, so where it meets the
|
|
257
|
+
// script is where the script starts and ends. No editor feature reads
|
|
258
|
+
// through it.
|
|
259
|
+
const tag = script.sourceNode.getStart(script.sourceFile);
|
|
260
|
+
const opened = script.sourceNode.template.getStart(script.sourceFile) + 1;
|
|
261
|
+
const closed = script.sourceNode.getEnd() - 1;
|
|
262
|
+
out.push([
|
|
263
|
+
awaits ? "cs.lift(await (async () => " : "cs.lift((() => ",
|
|
264
|
+
undefined,
|
|
265
|
+
tag,
|
|
266
|
+
opened - tag,
|
|
267
|
+
WRAPPER,
|
|
268
|
+
]);
|
|
269
|
+
emit(file, 0);
|
|
270
|
+
out.push([")())", undefined, closed, 1, WRAPPER]);
|
|
271
|
+
return out;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Whether a name is read as a value where it stands, rather than naming a
|
|
275
|
+
// property, an attribute, a label or what a declaration declares.
|
|
276
|
+
function isReference(
|
|
277
|
+
ts: typeof import("typescript"),
|
|
278
|
+
node: ts.Identifier,
|
|
279
|
+
): boolean {
|
|
280
|
+
const parent = node.parent;
|
|
281
|
+
if (
|
|
282
|
+
(ts.isPropertyAccessExpression(parent) ||
|
|
283
|
+
ts.isPropertyAssignment(parent) ||
|
|
284
|
+
ts.isMethodDeclaration(parent) ||
|
|
285
|
+
ts.isPropertyDeclaration(parent) ||
|
|
286
|
+
ts.isGetAccessorDeclaration(parent) ||
|
|
287
|
+
ts.isSetAccessorDeclaration(parent) ||
|
|
288
|
+
ts.isPropertySignature(parent) ||
|
|
289
|
+
ts.isMethodSignature(parent) ||
|
|
290
|
+
ts.isEnumMember(parent) ||
|
|
291
|
+
ts.isJsxAttribute(parent) ||
|
|
292
|
+
ts.isVariableDeclaration(parent) ||
|
|
293
|
+
ts.isParameter(parent) ||
|
|
294
|
+
ts.isFunctionDeclaration(parent) ||
|
|
295
|
+
ts.isFunctionExpression(parent) ||
|
|
296
|
+
ts.isClassDeclaration(parent) ||
|
|
297
|
+
ts.isClassExpression(parent) ||
|
|
298
|
+
ts.isTypeAliasDeclaration(parent) ||
|
|
299
|
+
ts.isInterfaceDeclaration(parent) ||
|
|
300
|
+
ts.isEnumDeclaration(parent) ||
|
|
301
|
+
ts.isTypeParameterDeclaration(parent)) &&
|
|
302
|
+
parent.name === node
|
|
303
|
+
) {
|
|
304
|
+
return false;
|
|
305
|
+
}
|
|
306
|
+
if (ts.isBindingElement(parent)) {
|
|
307
|
+
return false; // its name declares, its property name names a property
|
|
308
|
+
}
|
|
309
|
+
if (
|
|
310
|
+
(ts.isLabeledStatement(parent) ||
|
|
311
|
+
ts.isBreakStatement(parent) ||
|
|
312
|
+
ts.isContinueStatement(parent)) &&
|
|
313
|
+
parent.label === node
|
|
314
|
+
) {
|
|
315
|
+
return false;
|
|
316
|
+
}
|
|
317
|
+
if (
|
|
318
|
+
(ts.isJsxOpeningElement(parent) ||
|
|
319
|
+
ts.isJsxSelfClosingElement(parent) ||
|
|
320
|
+
ts.isJsxClosingElement(parent)) &&
|
|
321
|
+
parent.tagName === node
|
|
322
|
+
) {
|
|
323
|
+
return false; // an intrinsic element's name, or a host tag's (above)
|
|
324
|
+
}
|
|
325
|
+
return !(
|
|
326
|
+
ts.isQualifiedName(parent) ||
|
|
327
|
+
ts.isMetaProperty(parent) ||
|
|
328
|
+
ts.isJsxNamespacedName(parent)
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Whether a name stands in a type, which names types rather than values: all
|
|
333
|
+
// but what a `typeof` reads, and a class's `extends`.
|
|
334
|
+
function inTypePosition(
|
|
335
|
+
ts: typeof import("typescript"),
|
|
336
|
+
node: ts.Identifier,
|
|
337
|
+
): boolean {
|
|
338
|
+
for (let at: ts.Node = node; at.parent !== undefined; at = at.parent) {
|
|
339
|
+
const parent = at.parent;
|
|
340
|
+
if (ts.isTypeQueryNode(parent)) {
|
|
341
|
+
return false;
|
|
342
|
+
}
|
|
343
|
+
if (
|
|
344
|
+
ts.isExpressionWithTypeArguments(parent) &&
|
|
345
|
+
ts.isHeritageClause(parent.parent) &&
|
|
346
|
+
ts.isClassLike(parent.parent.parent)
|
|
347
|
+
) {
|
|
348
|
+
return false;
|
|
349
|
+
}
|
|
350
|
+
if (ts.isTypeNode(parent)) {
|
|
351
|
+
return true;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
return false;
|
|
355
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { SourceMapping } from "./buildMappings.js";
|
|
2
|
+
import type { Diagnostic } from "./diagnostics.js";
|
|
3
|
+
import { parseSourceText } from "./parseFile.js";
|
|
4
|
+
import { printVirtualCode } from "./printVirtualCode.js";
|
|
5
|
+
import { rewriteFile } from "./rewriteFile.js";
|
|
6
|
+
|
|
7
|
+
export interface Virtualized {
|
|
8
|
+
virtualCode: string;
|
|
9
|
+
mappings: SourceMapping[];
|
|
10
|
+
diagnostics: Diagnostic[];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function virtualize(
|
|
14
|
+
ts: typeof import("typescript"),
|
|
15
|
+
filePath: string,
|
|
16
|
+
sourceText: string,
|
|
17
|
+
): Virtualized {
|
|
18
|
+
const parsedFile = parseSourceText(ts, filePath, sourceText);
|
|
19
|
+
|
|
20
|
+
const rewrittenFile = rewriteFile(ts, parsedFile);
|
|
21
|
+
|
|
22
|
+
const { virtualCode, mappings } = printVirtualCode(
|
|
23
|
+
ts,
|
|
24
|
+
parsedFile,
|
|
25
|
+
rewrittenFile,
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
return { virtualCode, mappings, diagnostics: rewrittenFile.diagnostics };
|
|
29
|
+
}
|