@gi-tcg/gts-transpiler 0.4.3 → 0.4.5
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/dist/index.js +59 -30
- package/package.json +2 -2
- package/src/config.ts +2 -12
- package/src/transform/constants.ts +2 -11
- package/src/transform/volar/printer.ts +11 -1
- package/src/transform/volar/replacements.ts +15 -4
- package/src/transform/volar/walker.ts +72 -4
package/dist/index.js
CHANGED
|
@@ -713,17 +713,12 @@ const eraseTs = (ast) => {
|
|
|
713
713
|
};
|
|
714
714
|
//#endregion
|
|
715
715
|
//#region src/transform/constants.ts
|
|
716
|
-
const DEFAULT_SHORTCUT_FUNCTION_PRELUDES = [
|
|
717
|
-
|
|
718
|
-
"
|
|
719
|
-
"
|
|
720
|
-
"
|
|
721
|
-
"anemo",
|
|
722
|
-
"geo",
|
|
723
|
-
"dendro",
|
|
724
|
-
"omni"
|
|
716
|
+
const DEFAULT_SHORTCUT_FUNCTION_PRELUDES = ["$"];
|
|
717
|
+
const DEFAULT_QUERY_BINDINGS = [
|
|
718
|
+
"my",
|
|
719
|
+
"opp",
|
|
720
|
+
"macros"
|
|
725
721
|
];
|
|
726
|
-
const DEFAULT_QUERY_BINDINGS = ["my", "opp"];
|
|
727
722
|
//#endregion
|
|
728
723
|
//#region src/transform/gts.ts
|
|
729
724
|
const commonGtsVisitor = {
|
|
@@ -1245,10 +1240,11 @@ function applyReplacements(state, code, mappings) {
|
|
|
1245
1240
|
const lhs = `${payload.finalMetaType}_lhs`;
|
|
1246
1241
|
const requiredAttrsNs = `${payload.finalMetaType}_rans`;
|
|
1247
1242
|
const collectedAttrsExpr = `${payload.collectedAttrs.join(" | ") || "never"}`;
|
|
1248
|
-
const
|
|
1243
|
+
const length = payload.errorRange ? payload.errorRange[1] - payload.errorRange[0] : 0;
|
|
1244
|
+
const needleString = `"${requiredAttrsNs}_NeedleString${"0".repeat(length)}" as string as ${requiredAttrsNs}.DiagMsg`;
|
|
1249
1245
|
if (payload.errorRange) state.extraMappings.push({
|
|
1250
1246
|
sourceOffset: payload.errorRange[0],
|
|
1251
|
-
length
|
|
1247
|
+
length,
|
|
1252
1248
|
generatedNeedle: needleString
|
|
1253
1249
|
});
|
|
1254
1250
|
replacement = dedent`
|
|
@@ -1257,7 +1253,13 @@ function applyReplacements(state, code, mappings) {
|
|
|
1257
1253
|
type ${lhs} = typeof ${lhs};
|
|
1258
1254
|
namespace ${requiredAttrsNs} {
|
|
1259
1255
|
export type Collected = ${collectedAttrsExpr};
|
|
1260
|
-
export type Expected = {
|
|
1256
|
+
export type Expected = {
|
|
1257
|
+
[K in keyof ${payload.defType}]: ${lhs}[K] extends { required(this: ${lhs}): true } ? K : never;
|
|
1258
|
+
}[keyof ${payload.defType}];
|
|
1259
|
+
type DiagObj = {
|
|
1260
|
+
[K in Expected]: K extends Collected ? never : \`'\${K}' is a required attribute but not provided\`;
|
|
1261
|
+
}
|
|
1262
|
+
export type DiagMsg = DiagObj[Expected];
|
|
1261
1263
|
};
|
|
1262
1264
|
((_: ${requiredAttrsNs}.Expected extends ${requiredAttrsNs}.Collected ? string : ${requiredAttrsNs}.Expected) => 0)(${needleString});
|
|
1263
1265
|
`;
|
|
@@ -1291,7 +1293,7 @@ function applyReplacements(state, code, mappings) {
|
|
|
1291
1293
|
? ${payload.attrName} /* have duplicate, disable this */
|
|
1292
1294
|
: never
|
|
1293
1295
|
);
|
|
1294
|
-
let ${payload.lhs}!: { ${Meta}: ${payload.metaType} } & Omit<${payload.defType}, ${omittedKeys}>;
|
|
1296
|
+
let ${payload.lhs}!: ${payload.hintOnly ? `{}` : `{ ${Meta}: ${payload.metaType} }`} & Omit<${payload.defType}, ${omittedKeys}>;
|
|
1295
1297
|
`;
|
|
1296
1298
|
} else if (payload.type === "createBindingTyping") {
|
|
1297
1299
|
const typingIdLhs = `${payload.typingId}_lhs`;
|
|
@@ -1326,6 +1328,7 @@ function applyReplacements(state, code, mappings) {
|
|
|
1326
1328
|
//#endregion
|
|
1327
1329
|
//#region src/transform/volar/walker.ts
|
|
1328
1330
|
const EMPTY = { type: "EmptyStatement" };
|
|
1331
|
+
const ATTR_HINT_ATTR_NAME = JSON.stringify("~attrNameHint");
|
|
1329
1332
|
const enterVMFromRoot = (state) => {
|
|
1330
1333
|
let defTypeId = {
|
|
1331
1334
|
type: "Identifier",
|
|
@@ -1405,7 +1408,8 @@ const enterAttr = (state, attrName) => {
|
|
|
1405
1408
|
defType: defTypeId.name,
|
|
1406
1409
|
metaType: metaTypeId.name,
|
|
1407
1410
|
lhs: lhsId.name,
|
|
1408
|
-
attrName
|
|
1411
|
+
attrName,
|
|
1412
|
+
hintOnly: attrName === ATTR_HINT_ATTR_NAME
|
|
1409
1413
|
}));
|
|
1410
1414
|
return { lhsId };
|
|
1411
1415
|
};
|
|
@@ -1437,6 +1441,19 @@ const exitAttr = (state, returningId) => {
|
|
|
1437
1441
|
returnType: returningId.name
|
|
1438
1442
|
}));
|
|
1439
1443
|
};
|
|
1444
|
+
const insertHintStatement = (state, whiteSpaceStart, whiteSpaceEnd) => {
|
|
1445
|
+
const { lhsId } = enterAttr(state, ATTR_HINT_ATTR_NAME);
|
|
1446
|
+
state.typingPendingStatements.push({
|
|
1447
|
+
type: "GTSAttributeNameHintStatement",
|
|
1448
|
+
object: lhsId,
|
|
1449
|
+
whiteSpaceStart,
|
|
1450
|
+
whiteSpaceEnd
|
|
1451
|
+
});
|
|
1452
|
+
exitAttr(state, {
|
|
1453
|
+
type: "Identifier",
|
|
1454
|
+
name: `__gts_attrRet_hint_${state.idCounter++}`
|
|
1455
|
+
});
|
|
1456
|
+
};
|
|
1440
1457
|
const gtsToTypingsWalker = {
|
|
1441
1458
|
Program(node, { state, visit }) {
|
|
1442
1459
|
const body = [];
|
|
@@ -1601,11 +1618,11 @@ const gtsToTypingsWalker = {
|
|
|
1601
1618
|
}
|
|
1602
1619
|
}]
|
|
1603
1620
|
});
|
|
1621
|
+
enterVMFromAttr(state, returnValue);
|
|
1604
1622
|
if (body.namedAttributes) {
|
|
1605
|
-
enterVMFromAttr(state, returnValue);
|
|
1606
1623
|
visit(body.namedAttributes);
|
|
1607
1624
|
exitVM(state, body.namedAttributes.range);
|
|
1608
|
-
}
|
|
1625
|
+
} else exitVM(state, name.range);
|
|
1609
1626
|
if (bindingName) {
|
|
1610
1627
|
const export_ = node.bindingAccessModifier !== "private";
|
|
1611
1628
|
const typingId = {
|
|
@@ -1636,7 +1653,17 @@ const gtsToTypingsWalker = {
|
|
|
1636
1653
|
return EMPTY;
|
|
1637
1654
|
},
|
|
1638
1655
|
GTSNamedAttributeBlock(node, { state, visit }) {
|
|
1639
|
-
|
|
1656
|
+
const attributeListEnd = node.directAction?.range?.[0] ?? node.range?.[1] ?? -1;
|
|
1657
|
+
const attributeListStart = node.attributes[0]?.range?.[0] ?? attributeListEnd;
|
|
1658
|
+
if (node.range && attributeListStart > node.range[0] + 1) insertHintStatement(state, node.range[0] + 1, attributeListStart - 1);
|
|
1659
|
+
for (let i = 0; i < node.attributes.length; i++) {
|
|
1660
|
+
const attribute = node.attributes[i];
|
|
1661
|
+
visit(attribute);
|
|
1662
|
+
let nextTokenStart;
|
|
1663
|
+
if (i < node.attributes.length - 1) nextTokenStart = node.attributes[i + 1].range?.[0] ?? -1;
|
|
1664
|
+
else nextTokenStart = attributeListEnd;
|
|
1665
|
+
if (attribute.range && nextTokenStart > attribute.range[1]) insertHintStatement(state, attribute.range[1], nextTokenStart - 1);
|
|
1666
|
+
}
|
|
1640
1667
|
if (node.directAction) {
|
|
1641
1668
|
const stubStatement = {
|
|
1642
1669
|
type: "ExpressionStatement",
|
|
@@ -1693,6 +1720,7 @@ const gtsToTypingsWalker = {
|
|
|
1693
1720
|
}
|
|
1694
1721
|
}]
|
|
1695
1722
|
});
|
|
1723
|
+
exitAttr(state, returnValue);
|
|
1696
1724
|
}
|
|
1697
1725
|
return EMPTY;
|
|
1698
1726
|
},
|
|
@@ -1733,6 +1761,7 @@ function getPrintOptions(source, state) {
|
|
|
1733
1761
|
if (state.attributeNameNodes.has(node)) return false;
|
|
1734
1762
|
return state.sourceNodes.has(node);
|
|
1735
1763
|
},
|
|
1764
|
+
printCommentsOnUntouchedNodes: true,
|
|
1736
1765
|
getLeadingComments: (node) => node.leadingComments,
|
|
1737
1766
|
getTrailingComments: (node) => node.trailingComments,
|
|
1738
1767
|
getMappingData: () => DEFAULT_VOLAR_MAPPING_DATA,
|
|
@@ -1802,6 +1831,12 @@ function getPrintOptions(source, state) {
|
|
|
1802
1831
|
end: state.contentStartOffset + 1
|
|
1803
1832
|
}, context.generatedOffset, context.generatedOffset + 1, DEFAULT_VOLAR_MAPPING_DATA);
|
|
1804
1833
|
}
|
|
1834
|
+
},
|
|
1835
|
+
GTSAttributeNameHintStatement(node, context) {
|
|
1836
|
+
context.writeNode(node.object);
|
|
1837
|
+
context.write(".");
|
|
1838
|
+
context.writeSource(node.whiteSpaceStart, node.whiteSpaceEnd);
|
|
1839
|
+
context.write(";");
|
|
1805
1840
|
}
|
|
1806
1841
|
},
|
|
1807
1842
|
experimentalGetLeftParenSourceRange: (node) => {
|
|
@@ -1968,18 +2003,12 @@ function transform(ast, option = {}, sourceInfo = {}) {
|
|
|
1968
2003
|
const DEFAULT_GTS_CONFIG = {
|
|
1969
2004
|
runtimeImportSource: "@gi-tcg/gts-runtime",
|
|
1970
2005
|
providerImportSource: "@gi-tcg/core/gts",
|
|
1971
|
-
shortcutFunctionPreludes: [
|
|
1972
|
-
|
|
1973
|
-
"
|
|
1974
|
-
"
|
|
1975
|
-
"
|
|
1976
|
-
|
|
1977
|
-
"geo",
|
|
1978
|
-
"dendro",
|
|
1979
|
-
"omni",
|
|
1980
|
-
"$"
|
|
1981
|
-
],
|
|
1982
|
-
queryBindings: ["my", "opp"]
|
|
2006
|
+
shortcutFunctionPreludes: ["$"],
|
|
2007
|
+
queryBindings: [
|
|
2008
|
+
"my",
|
|
2009
|
+
"opp",
|
|
2010
|
+
"macros"
|
|
2011
|
+
]
|
|
1983
2012
|
};
|
|
1984
2013
|
function* resolveGtsConfigImpl(filePath, inlineConfig = {}, options) {
|
|
1985
2014
|
const pathModule = options.pathModule || browserPath;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gi-tcg/gts-transpiler",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.5",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/piovium/gts.git"
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"@sveltejs/acorn-typescript": "^1.0.8",
|
|
23
23
|
"acorn": "^8.15.0",
|
|
24
24
|
"dedent": "^1.7.2",
|
|
25
|
-
"espolar": "^0.6.
|
|
25
|
+
"espolar": "^0.6.1",
|
|
26
26
|
"esrap": "2.2.1",
|
|
27
27
|
"magic-string": "^0.30.21",
|
|
28
28
|
"path-browserify-esm": "^1.0.6",
|
package/src/config.ts
CHANGED
|
@@ -33,18 +33,8 @@ export interface ResolveGtsConfigAsyncOptions extends ResolveGtsConfigBaseOption
|
|
|
33
33
|
const DEFAULT_GTS_CONFIG: Required<GtsConfig> = {
|
|
34
34
|
runtimeImportSource: "@gi-tcg/gts-runtime",
|
|
35
35
|
providerImportSource: "@gi-tcg/core/gts",
|
|
36
|
-
shortcutFunctionPreludes: [
|
|
37
|
-
|
|
38
|
-
"hydro",
|
|
39
|
-
"pyro",
|
|
40
|
-
"electro",
|
|
41
|
-
"anemo",
|
|
42
|
-
"geo",
|
|
43
|
-
"dendro",
|
|
44
|
-
"omni",
|
|
45
|
-
"$",
|
|
46
|
-
],
|
|
47
|
-
queryBindings: ["my", "opp"],
|
|
36
|
+
shortcutFunctionPreludes: ["$"],
|
|
37
|
+
queryBindings: ["my", "opp", "macros"],
|
|
48
38
|
};
|
|
49
39
|
|
|
50
40
|
function* resolveGtsConfigImpl(
|
|
@@ -1,11 +1,2 @@
|
|
|
1
|
-
export const DEFAULT_SHORTCUT_FUNCTION_PRELUDES: string[] = [
|
|
2
|
-
|
|
3
|
-
"hydro",
|
|
4
|
-
"pyro",
|
|
5
|
-
"electro",
|
|
6
|
-
"anemo",
|
|
7
|
-
"geo",
|
|
8
|
-
"dendro",
|
|
9
|
-
"omni",
|
|
10
|
-
];
|
|
11
|
-
export const DEFAULT_QUERY_BINDINGS: string[] = ["my", "opp"];
|
|
1
|
+
export const DEFAULT_SHORTCUT_FUNCTION_PRELUDES: string[] = ["$"];
|
|
2
|
+
export const DEFAULT_QUERY_BINDINGS: string[] = ["my", "opp", "macros"];
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
type AST as EspolarAST,
|
|
11
11
|
defaultPrinters,
|
|
12
12
|
type SourceRange,
|
|
13
|
+
type PrinterContext,
|
|
13
14
|
} from "espolar";
|
|
14
15
|
import type { CodeInformation } from "@volar/language-core";
|
|
15
16
|
import {
|
|
@@ -19,7 +20,7 @@ import {
|
|
|
19
20
|
LITERAL_FROM_ID_MAPPING_DATA,
|
|
20
21
|
VERIFICATION_ONLY_MAPPING_DATA,
|
|
21
22
|
} from "./mappings.ts";
|
|
22
|
-
import type { TypingTranspileState } from "./walker.ts";
|
|
23
|
+
import type { TypingTranspileState, GTSAttributeNameHintStatement } from "./walker.ts";
|
|
23
24
|
|
|
24
25
|
export function getPrintOptions(
|
|
25
26
|
source: string,
|
|
@@ -36,6 +37,7 @@ export function getPrintOptions(
|
|
|
36
37
|
}
|
|
37
38
|
return state.sourceNodes.has(node as Node);
|
|
38
39
|
},
|
|
40
|
+
printCommentsOnUntouchedNodes: true,
|
|
39
41
|
getLeadingComments: (node) => (node as Node).leadingComments,
|
|
40
42
|
getTrailingComments: (node) => (node as Node).trailingComments,
|
|
41
43
|
getMappingData: () => DEFAULT_VOLAR_MAPPING_DATA,
|
|
@@ -186,6 +188,14 @@ export function getPrintOptions(
|
|
|
186
188
|
);
|
|
187
189
|
}
|
|
188
190
|
},
|
|
191
|
+
// @ts-expect-error This is a custom node type that don't have typing.
|
|
192
|
+
// @see `GTSAttributeNameHintStatement`
|
|
193
|
+
GTSAttributeNameHintStatement(node: GTSAttributeNameHintStatement, context: PrinterContext<CodeInformation>) {
|
|
194
|
+
context.writeNode(node.object as EspolarAST.Node);
|
|
195
|
+
context.write(".");
|
|
196
|
+
context.writeSource(node.whiteSpaceStart, node.whiteSpaceEnd);
|
|
197
|
+
context.write(";");
|
|
198
|
+
}
|
|
189
199
|
},
|
|
190
200
|
// Enable triggering signature completion
|
|
191
201
|
experimentalGetLeftParenSourceRange: (node) => {
|
|
@@ -38,6 +38,7 @@ type ReplacementPayload =
|
|
|
38
38
|
metaType: string;
|
|
39
39
|
lhs: string;
|
|
40
40
|
attrName: string;
|
|
41
|
+
hintOnly: boolean;
|
|
41
42
|
}
|
|
42
43
|
| {
|
|
43
44
|
type: "createBindingTyping";
|
|
@@ -121,11 +122,15 @@ export function applyReplacements(
|
|
|
121
122
|
const lhs = `${payload.finalMetaType}_lhs`;
|
|
122
123
|
const requiredAttrsNs = `${payload.finalMetaType}_rans`;
|
|
123
124
|
const collectedAttrsExpr = `${payload.collectedAttrs.join(" | ") || "never"}`;
|
|
124
|
-
const
|
|
125
|
+
const length = payload.errorRange
|
|
126
|
+
? payload.errorRange[1] - payload.errorRange[0]
|
|
127
|
+
: 0;
|
|
128
|
+
// Ensure that generated needle string is longer than error range so that error squiggle can cover all
|
|
129
|
+
const needleString = `"${requiredAttrsNs}_NeedleString${"0".repeat(length)}" as string as ${requiredAttrsNs}.DiagMsg`;
|
|
125
130
|
if (payload.errorRange) {
|
|
126
131
|
state.extraMappings.push({
|
|
127
132
|
sourceOffset: payload.errorRange[0],
|
|
128
|
-
length
|
|
133
|
+
length,
|
|
129
134
|
generatedNeedle: needleString,
|
|
130
135
|
});
|
|
131
136
|
}
|
|
@@ -135,7 +140,13 @@ export function applyReplacements(
|
|
|
135
140
|
type ${lhs} = typeof ${lhs};
|
|
136
141
|
namespace ${requiredAttrsNs} {
|
|
137
142
|
export type Collected = ${collectedAttrsExpr};
|
|
138
|
-
export type Expected = {
|
|
143
|
+
export type Expected = {
|
|
144
|
+
[K in keyof ${payload.defType}]: ${lhs}[K] extends { required(this: ${lhs}): true } ? K : never;
|
|
145
|
+
}[keyof ${payload.defType}];
|
|
146
|
+
type DiagObj = {
|
|
147
|
+
[K in Expected]: K extends Collected ? never : \`'\${K}' is a required attribute but not provided\`;
|
|
148
|
+
}
|
|
149
|
+
export type DiagMsg = DiagObj[Expected];
|
|
139
150
|
};
|
|
140
151
|
((_: ${requiredAttrsNs}.Expected extends ${requiredAttrsNs}.Collected ? string : ${requiredAttrsNs}.Expected) => 0)(${needleString});
|
|
141
152
|
`;
|
|
@@ -169,7 +180,7 @@ export function applyReplacements(
|
|
|
169
180
|
? ${payload.attrName} /* have duplicate, disable this */
|
|
170
181
|
: never
|
|
171
182
|
);
|
|
172
|
-
let ${payload.lhs}!: { ${Meta}: ${payload.metaType} } & Omit<${payload.defType}, ${omittedKeys}>;
|
|
183
|
+
let ${payload.lhs}!: ${payload.hintOnly ? `{}` : `{ ${Meta}: ${payload.metaType} }`} & Omit<${payload.defType}, ${omittedKeys}>;
|
|
173
184
|
`;
|
|
174
185
|
} else if (payload.type === "createBindingTyping") {
|
|
175
186
|
const typingIdLhs = `${payload.typingId}_lhs`;
|
|
@@ -92,7 +92,25 @@ export interface TypingTranspileState extends TranspileState {
|
|
|
92
92
|
contentStartOffset: number;
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
+
/**
|
|
96
|
+
* Map whitespaces inside named attribute blocks to include a "NameHintStatement", which printed
|
|
97
|
+
* as following:
|
|
98
|
+
* ```ts
|
|
99
|
+
* __gts_attr_obj. ;
|
|
100
|
+
* // ^~~~~~ these whitespaces are mapped from source
|
|
101
|
+
* ```
|
|
102
|
+
* so that when user press Ctrl+Space inside whitespace characters, they can get hint of available
|
|
103
|
+
* attribute names inside this block.
|
|
104
|
+
*/
|
|
105
|
+
export interface GTSAttributeNameHintStatement {
|
|
106
|
+
type: "GTSAttributeNameHintStatement";
|
|
107
|
+
object: Identifier;
|
|
108
|
+
whiteSpaceStart: number;
|
|
109
|
+
whiteSpaceEnd: number;
|
|
110
|
+
}
|
|
111
|
+
|
|
95
112
|
const EMPTY: EmptyStatement = { type: "EmptyStatement" };
|
|
113
|
+
const ATTR_HINT_ATTR_NAME = JSON.stringify("~attrNameHint");
|
|
96
114
|
|
|
97
115
|
const enterVMFromRoot = (state: TypingTranspileState) => {
|
|
98
116
|
let defTypeId: Identifier = {
|
|
@@ -174,7 +192,7 @@ const enterAttr = (
|
|
|
174
192
|
const defTypeId = state.vmDefTypeIdStack.at(-1);
|
|
175
193
|
const metaTypeId = state.metaTypeIdStack.at(-1);
|
|
176
194
|
if (!defTypeId || !metaTypeId) {
|
|
177
|
-
//
|
|
195
|
+
// FIXME error handling?
|
|
178
196
|
return { lhsId: { type: "Identifier", name: "__gts_invalid_attr_obj" } };
|
|
179
197
|
}
|
|
180
198
|
state.attrsOfCurrentVm.at(-1)!.push(attrName);
|
|
@@ -189,6 +207,7 @@ const enterAttr = (
|
|
|
189
207
|
metaType: metaTypeId.name,
|
|
190
208
|
lhs: lhsId.name,
|
|
191
209
|
attrName,
|
|
210
|
+
hintOnly: attrName === ATTR_HINT_ATTR_NAME,
|
|
192
211
|
}),
|
|
193
212
|
);
|
|
194
213
|
return { lhsId: lhsId };
|
|
@@ -238,6 +257,25 @@ const exitAttr = (state: TypingTranspileState, returningId: Identifier) => {
|
|
|
238
257
|
);
|
|
239
258
|
};
|
|
240
259
|
|
|
260
|
+
const insertHintStatement = (
|
|
261
|
+
state: TypingTranspileState,
|
|
262
|
+
whiteSpaceStart: number,
|
|
263
|
+
whiteSpaceEnd: number,
|
|
264
|
+
) => {
|
|
265
|
+
const { lhsId } = enterAttr(state, ATTR_HINT_ATTR_NAME);
|
|
266
|
+
state.typingPendingStatements.push({
|
|
267
|
+
type: "GTSAttributeNameHintStatement",
|
|
268
|
+
object: lhsId,
|
|
269
|
+
whiteSpaceStart,
|
|
270
|
+
whiteSpaceEnd,
|
|
271
|
+
} satisfies GTSAttributeNameHintStatement as any);
|
|
272
|
+
const returnValue: Identifier = {
|
|
273
|
+
type: "Identifier",
|
|
274
|
+
name: `__gts_attrRet_hint_${state.idCounter++}`,
|
|
275
|
+
};
|
|
276
|
+
exitAttr(state, returnValue);
|
|
277
|
+
};
|
|
278
|
+
|
|
241
279
|
export const gtsToTypingsWalker: Visitors<Node, TypingTranspileState> = {
|
|
242
280
|
Program(node, { state, visit }) {
|
|
243
281
|
const body: Program["body"] = [];
|
|
@@ -434,10 +472,12 @@ export const gtsToTypingsWalker: Visitors<Node, TypingTranspileState> = {
|
|
|
434
472
|
},
|
|
435
473
|
],
|
|
436
474
|
});
|
|
475
|
+
enterVMFromAttr(state, returnValue);
|
|
437
476
|
if (body.namedAttributes) {
|
|
438
|
-
enterVMFromAttr(state, returnValue);
|
|
439
477
|
visit(body.namedAttributes);
|
|
440
478
|
exitVM(state, body.namedAttributes.range);
|
|
479
|
+
} else {
|
|
480
|
+
exitVM(state, name.range);
|
|
441
481
|
}
|
|
442
482
|
if (bindingName) {
|
|
443
483
|
const export_ = node.bindingAccessModifier !== "private";
|
|
@@ -469,8 +509,35 @@ export const gtsToTypingsWalker: Visitors<Node, TypingTranspileState> = {
|
|
|
469
509
|
return EMPTY;
|
|
470
510
|
},
|
|
471
511
|
GTSNamedAttributeBlock(node, { state, visit }) {
|
|
472
|
-
|
|
473
|
-
|
|
512
|
+
// Insert hint statement around each attribute name:
|
|
513
|
+
// ```
|
|
514
|
+
// define foo {
|
|
515
|
+
// // (1) hidden hint
|
|
516
|
+
// bar 1; // (2a) hidden hint
|
|
517
|
+
// baz 2; // (2b) hidden hint
|
|
518
|
+
// }
|
|
519
|
+
// ```
|
|
520
|
+
const attributeListEnd =
|
|
521
|
+
node.directAction?.range?.[0] ?? node.range?.[1] ?? -1;
|
|
522
|
+
const attributeListStart =
|
|
523
|
+
node.attributes[0]?.range?.[0] ?? attributeListEnd;
|
|
524
|
+
// (1)
|
|
525
|
+
if (node.range && attributeListStart > node.range[0] + 1) {
|
|
526
|
+
insertHintStatement(state, node.range[0] + 1, attributeListStart - 1);
|
|
527
|
+
}
|
|
528
|
+
for (let i = 0; i < node.attributes.length; i++) {
|
|
529
|
+
const attribute = node.attributes[i];
|
|
530
|
+
visit(attribute);
|
|
531
|
+
let nextTokenStart: number;
|
|
532
|
+
if (i < node.attributes.length - 1) {
|
|
533
|
+
nextTokenStart = node.attributes[i + 1].range?.[0] ?? -1;
|
|
534
|
+
} else {
|
|
535
|
+
nextTokenStart = attributeListEnd;
|
|
536
|
+
}
|
|
537
|
+
// (2)
|
|
538
|
+
if (attribute.range && nextTokenStart > attribute.range[1]) {
|
|
539
|
+
insertHintStatement(state, attribute.range[1], nextTokenStart - 1);
|
|
540
|
+
}
|
|
474
541
|
}
|
|
475
542
|
if (node.directAction) {
|
|
476
543
|
const stubStatement: ExpressionStatement = {
|
|
@@ -527,6 +594,7 @@ export const gtsToTypingsWalker: Visitors<Node, TypingTranspileState> = {
|
|
|
527
594
|
},
|
|
528
595
|
],
|
|
529
596
|
});
|
|
597
|
+
exitAttr(state, returnValue);
|
|
530
598
|
}
|
|
531
599
|
return EMPTY;
|
|
532
600
|
},
|