@tsonic/emitter 0.0.73 → 0.0.74
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/.tsbuildinfo +1 -1
- package/dist/adapter-generator.d.ts.map +1 -1
- package/dist/adapter-generator.js +2 -1
- package/dist/adapter-generator.js.map +1 -1
- package/dist/constants.d.ts +3 -2
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +15 -6
- package/dist/constants.js.map +1 -1
- package/dist/core/format/attributes.d.ts.map +1 -1
- package/dist/core/format/attributes.js +5 -56
- package/dist/core/format/attributes.js.map +1 -1
- package/dist/core/format/attributes.test.js +1 -1
- package/dist/core/format/attributes.test.js.map +1 -1
- package/dist/core/format/backend-ast/builders.d.ts +13 -0
- package/dist/core/format/backend-ast/builders.d.ts.map +1 -0
- package/dist/core/format/backend-ast/builders.js +169 -0
- package/dist/core/format/backend-ast/builders.js.map +1 -0
- package/dist/core/format/backend-ast/builders.test.d.ts +2 -0
- package/dist/core/format/backend-ast/builders.test.d.ts.map +1 -0
- package/dist/core/format/backend-ast/builders.test.js +258 -0
- package/dist/core/format/backend-ast/builders.test.js.map +1 -0
- package/dist/core/format/backend-ast/index.d.ts +3 -2
- package/dist/core/format/backend-ast/index.d.ts.map +1 -1
- package/dist/core/format/backend-ast/index.js +2 -1
- package/dist/core/format/backend-ast/index.js.map +1 -1
- package/dist/core/format/backend-ast/invariants.test.d.ts +2 -0
- package/dist/core/format/backend-ast/invariants.test.d.ts.map +1 -0
- package/dist/core/format/backend-ast/invariants.test.js +72 -0
- package/dist/core/format/backend-ast/invariants.test.js.map +1 -0
- package/dist/core/format/backend-ast/printer.d.ts +1 -1
- package/dist/core/format/backend-ast/printer.d.ts.map +1 -1
- package/dist/core/format/backend-ast/printer.js +362 -119
- package/dist/core/format/backend-ast/printer.js.map +1 -1
- package/dist/core/format/backend-ast/printer.test.d.ts +2 -0
- package/dist/core/format/backend-ast/printer.test.d.ts.map +1 -0
- package/dist/core/format/backend-ast/printer.test.js +796 -0
- package/dist/core/format/backend-ast/printer.test.js.map +1 -0
- package/dist/core/format/backend-ast/types.d.ts +66 -14
- package/dist/core/format/backend-ast/types.d.ts.map +1 -1
- package/dist/core/format/backend-ast/utils.d.ts +12 -8
- package/dist/core/format/backend-ast/utils.d.ts.map +1 -1
- package/dist/core/format/backend-ast/utils.js +222 -19
- package/dist/core/format/backend-ast/utils.js.map +1 -1
- package/dist/core/format/backend-ast/utils.test.d.ts +2 -0
- package/dist/core/format/backend-ast/utils.test.d.ts.map +1 -0
- package/dist/core/format/backend-ast/utils.test.js +142 -0
- package/dist/core/format/backend-ast/utils.test.js.map +1 -0
- package/dist/core/format/module-emitter/assembly.d.ts +2 -2
- package/dist/core/format/module-emitter/assembly.d.ts.map +1 -1
- package/dist/core/format/module-emitter/assembly.js +7 -3
- package/dist/core/format/module-emitter/assembly.js.map +1 -1
- package/dist/core/format/module-emitter/header.d.ts +2 -1
- package/dist/core/format/module-emitter/header.d.ts.map +1 -1
- package/dist/core/format/module-emitter/header.js +2 -2
- package/dist/core/format/module-emitter/header.js.map +1 -1
- package/dist/core/format/module-emitter/orchestrator.js +1 -1
- package/dist/core/format/module-emitter/orchestrator.js.map +1 -1
- package/dist/core/format/module-emitter/static-container.d.ts.map +1 -1
- package/dist/core/format/module-emitter/static-container.js +3 -5
- package/dist/core/format/module-emitter/static-container.js.map +1 -1
- package/dist/core/module-emitter.test.js +1 -0
- package/dist/core/module-emitter.test.js.map +1 -1
- package/dist/core/semantic/boolean-context.d.ts.map +1 -1
- package/dist/core/semantic/boolean-context.js +45 -49
- package/dist/core/semantic/boolean-context.js.map +1 -1
- package/dist/core/semantic/imports.d.ts.map +1 -1
- package/dist/core/semantic/imports.js +16 -15
- package/dist/core/semantic/imports.js.map +1 -1
- package/dist/core/semantic/imports.test.js.map +1 -1
- package/dist/core/semantic/type-resolution.js +1 -2
- package/dist/core/semantic/type-resolution.js.map +1 -1
- package/dist/emitter-types/core.d.ts +19 -10
- package/dist/emitter-types/core.d.ts.map +1 -1
- package/dist/emitter.d.ts.map +1 -1
- package/dist/emitter.js +124 -44
- package/dist/emitter.js.map +1 -1
- package/dist/expression-emitter.d.ts.map +1 -1
- package/dist/expression-emitter.js +24 -43
- package/dist/expression-emitter.js.map +1 -1
- package/dist/expressions/access.d.ts.map +1 -1
- package/dist/expressions/access.js +11 -28
- package/dist/expressions/access.js.map +1 -1
- package/dist/expressions/calls/call-analysis.d.ts +0 -10
- package/dist/expressions/calls/call-analysis.d.ts.map +1 -1
- package/dist/expressions/calls/call-analysis.js +3 -62
- package/dist/expressions/calls/call-analysis.js.map +1 -1
- package/dist/expressions/calls/call-emitter.d.ts.map +1 -1
- package/dist/expressions/calls/call-emitter.js +89 -151
- package/dist/expressions/calls/call-emitter.js.map +1 -1
- package/dist/expressions/calls/new-emitter.d.ts.map +1 -1
- package/dist/expressions/calls/new-emitter.js +36 -69
- package/dist/expressions/calls/new-emitter.js.map +1 -1
- package/dist/expressions/collections.d.ts +3 -0
- package/dist/expressions/collections.d.ts.map +1 -1
- package/dist/expressions/collections.js +43 -70
- package/dist/expressions/collections.js.map +1 -1
- package/dist/expressions/functions.d.ts.map +1 -1
- package/dist/expressions/functions.js +1 -7
- package/dist/expressions/functions.js.map +1 -1
- package/dist/expressions/identifiers.d.ts.map +1 -1
- package/dist/expressions/identifiers.js +23 -44
- package/dist/expressions/identifiers.js.map +1 -1
- package/dist/expressions/index.test.js +128 -0
- package/dist/expressions/index.test.js.map +1 -1
- package/dist/expressions/literals.d.ts.map +1 -1
- package/dist/expressions/literals.js +9 -41
- package/dist/expressions/literals.js.map +1 -1
- package/dist/expressions/operators/assignment-emitter.d.ts.map +1 -1
- package/dist/expressions/operators/assignment-emitter.js +2 -6
- package/dist/expressions/operators/assignment-emitter.js.map +1 -1
- package/dist/expressions/operators/binary-emitter.d.ts.map +1 -1
- package/dist/expressions/operators/binary-emitter.js +16 -32
- package/dist/expressions/operators/binary-emitter.js.map +1 -1
- package/dist/expressions/operators/logical-emitter.d.ts.map +1 -1
- package/dist/expressions/operators/logical-emitter.js +1 -3
- package/dist/expressions/operators/logical-emitter.js.map +1 -1
- package/dist/expressions/operators/unary-emitter.d.ts.map +1 -1
- package/dist/expressions/operators/unary-emitter.js +9 -20
- package/dist/expressions/operators/unary-emitter.js.map +1 -1
- package/dist/expressions/other.d.ts.map +1 -1
- package/dist/expressions/other.js +6 -11
- package/dist/expressions/other.js.map +1 -1
- package/dist/generator-exchange.d.ts.map +1 -1
- package/dist/generator-exchange.js +3 -2
- package/dist/generator-exchange.js.map +1 -1
- package/dist/generator-wrapper.d.ts.map +1 -1
- package/dist/generator-wrapper.js +27 -56
- package/dist/generator-wrapper.js.map +1 -1
- package/dist/integration.test.js +1 -1
- package/dist/integration.test.js.map +1 -1
- package/dist/json-aot-generic.test.js +3 -0
- package/dist/json-aot-generic.test.js.map +1 -1
- package/dist/patterns.d.ts.map +1 -1
- package/dist/patterns.js +19 -40
- package/dist/patterns.js.map +1 -1
- package/dist/statements/classes/members/methods.d.ts.map +1 -1
- package/dist/statements/classes/members/methods.js +3 -9
- package/dist/statements/classes/members/methods.js.map +1 -1
- package/dist/statements/classes/parameters.d.ts.map +1 -1
- package/dist/statements/classes/parameters.js +2 -1
- package/dist/statements/classes/parameters.js.map +1 -1
- package/dist/statements/classes/properties.d.ts.map +1 -1
- package/dist/statements/classes/properties.js +5 -16
- package/dist/statements/classes/properties.js.map +1 -1
- package/dist/statements/control/conditionals/guard-analysis.d.ts +2 -1
- package/dist/statements/control/conditionals/guard-analysis.d.ts.map +1 -1
- package/dist/statements/control/conditionals/guard-analysis.js +19 -6
- package/dist/statements/control/conditionals/guard-analysis.js.map +1 -1
- package/dist/statements/control/conditionals/if-emitter.d.ts.map +1 -1
- package/dist/statements/control/conditionals/if-emitter.js +14 -9
- package/dist/statements/control/conditionals/if-emitter.js.map +1 -1
- package/dist/statements/control/exceptions.d.ts.map +1 -1
- package/dist/statements/control/exceptions.js +2 -4
- package/dist/statements/control/exceptions.js.map +1 -1
- package/dist/statements/control/loops.d.ts.map +1 -1
- package/dist/statements/control/loops.js +3 -5
- package/dist/statements/control/loops.js.map +1 -1
- package/dist/statements/declarations/classes.d.ts.map +1 -1
- package/dist/statements/declarations/classes.js +2 -4
- package/dist/statements/declarations/classes.js.map +1 -1
- package/dist/statements/declarations/functions.d.ts.map +1 -1
- package/dist/statements/declarations/functions.js +36 -66
- package/dist/statements/declarations/functions.js.map +1 -1
- package/dist/statements/declarations/interfaces-mutable-storage.test.js +10 -2
- package/dist/statements/declarations/interfaces-mutable-storage.test.js.map +1 -1
- package/dist/statements/declarations/interfaces.d.ts.map +1 -1
- package/dist/statements/declarations/interfaces.js +4 -12
- package/dist/statements/declarations/interfaces.js.map +1 -1
- package/dist/statements/declarations/type-aliases.d.ts.map +1 -1
- package/dist/statements/declarations/type-aliases.js +3 -8
- package/dist/statements/declarations/type-aliases.js.map +1 -1
- package/dist/statements/declarations/variables.d.ts.map +1 -1
- package/dist/statements/declarations/variables.js +39 -37
- package/dist/statements/declarations/variables.js.map +1 -1
- package/dist/statements/index.test.js +94 -8
- package/dist/statements/index.test.js.map +1 -1
- package/dist/types/dictionaries.d.ts.map +1 -1
- package/dist/types/dictionaries.js +5 -5
- package/dist/types/dictionaries.js.map +1 -1
- package/dist/types/functions.d.ts.map +1 -1
- package/dist/types/functions.js +5 -25
- package/dist/types/functions.js.map +1 -1
- package/dist/types/primitives.d.ts.map +1 -1
- package/dist/types/primitives.js.map +1 -1
- package/dist/types/references.d.ts.map +1 -1
- package/dist/types/references.js +65 -132
- package/dist/types/references.js.map +1 -1
- package/dist/types/references.test.js +63 -51
- package/dist/types/references.test.js.map +1 -1
- package/dist/types/tuples.d.ts.map +1 -1
- package/dist/types/tuples.js +7 -17
- package/dist/types/tuples.js.map +1 -1
- package/dist/types/unions.d.ts.map +1 -1
- package/dist/types/unions.js +2 -5
- package/dist/types/unions.js.map +1 -1
- package/package.json +2 -2
- package/dist/expressions/parentheses.d.ts +0 -4
- package/dist/expressions/parentheses.d.ts.map +0 -1
- package/dist/expressions/parentheses.js +0 -91
- package/dist/expressions/parentheses.js.map +0 -1
|
@@ -7,6 +7,203 @@
|
|
|
7
7
|
* Parenthesization is derived from operator precedence tables,
|
|
8
8
|
* not from advisory metadata on fragments.
|
|
9
9
|
*/
|
|
10
|
+
const escapeCSharpStringLiteral = (value) => value
|
|
11
|
+
.replace(/\\/g, "\\\\")
|
|
12
|
+
.replace(/"/g, '\\"')
|
|
13
|
+
.replace(/\n/g, "\\n")
|
|
14
|
+
.replace(/\r/g, "\\r")
|
|
15
|
+
.replace(/\t/g, "\\t");
|
|
16
|
+
const escapeCSharpCharLiteral = (value) => {
|
|
17
|
+
switch (value) {
|
|
18
|
+
case "'":
|
|
19
|
+
return "\\'";
|
|
20
|
+
case "\\":
|
|
21
|
+
return "\\\\";
|
|
22
|
+
case "\n":
|
|
23
|
+
return "\\n";
|
|
24
|
+
case "\r":
|
|
25
|
+
return "\\r";
|
|
26
|
+
case "\t":
|
|
27
|
+
return "\\t";
|
|
28
|
+
case "\0":
|
|
29
|
+
return "\\0";
|
|
30
|
+
default:
|
|
31
|
+
return value;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
const printTrivia = (trivia) => {
|
|
35
|
+
switch (trivia.kind) {
|
|
36
|
+
case "singleLineCommentTrivia":
|
|
37
|
+
return `// ${trivia.text}`;
|
|
38
|
+
case "blankLineTrivia":
|
|
39
|
+
return "";
|
|
40
|
+
default: {
|
|
41
|
+
const exhaustive = trivia;
|
|
42
|
+
throw new Error(`ICE: Unhandled trivia kind '${exhaustive.kind}' in printTrivia`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
const nameMayPrintColon = (name) => name.aliasQualifier !== undefined;
|
|
47
|
+
const typeMayPrintColon = (type) => {
|
|
48
|
+
switch (type.kind) {
|
|
49
|
+
case "predefinedType":
|
|
50
|
+
case "varType":
|
|
51
|
+
return false;
|
|
52
|
+
case "identifierType":
|
|
53
|
+
return type.typeArguments?.some(typeMayPrintColon) === true;
|
|
54
|
+
case "qualifiedIdentifierType":
|
|
55
|
+
return (nameMayPrintColon(type.name) ||
|
|
56
|
+
type.typeArguments?.some(typeMayPrintColon) === true);
|
|
57
|
+
case "nullableType":
|
|
58
|
+
return typeMayPrintColon(type.underlyingType);
|
|
59
|
+
case "arrayType":
|
|
60
|
+
return typeMayPrintColon(type.elementType);
|
|
61
|
+
case "pointerType":
|
|
62
|
+
return typeMayPrintColon(type.elementType);
|
|
63
|
+
case "tupleType":
|
|
64
|
+
return type.elements.some((element) => typeMayPrintColon(element.type));
|
|
65
|
+
default: {
|
|
66
|
+
const exhaustive = type;
|
|
67
|
+
throw new Error(`ICE: Unhandled type AST kind '${exhaustive.kind}' in typeMayPrintColon`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
const patternMayPrintColon = (pattern) => {
|
|
72
|
+
switch (pattern.kind) {
|
|
73
|
+
case "typePattern":
|
|
74
|
+
case "declarationPattern":
|
|
75
|
+
return typeMayPrintColon(pattern.type);
|
|
76
|
+
case "varPattern":
|
|
77
|
+
case "discardPattern":
|
|
78
|
+
return false;
|
|
79
|
+
case "constantPattern":
|
|
80
|
+
return expressionMayPrintColon(pattern.expression);
|
|
81
|
+
case "negatedPattern":
|
|
82
|
+
return patternMayPrintColon(pattern.pattern);
|
|
83
|
+
default: {
|
|
84
|
+
const exhaustive = pattern;
|
|
85
|
+
throw new Error(`ICE: Unhandled pattern AST kind '${exhaustive.kind}' in patternMayPrintColon`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
const expressionMayPrintColon = (expr) => {
|
|
90
|
+
switch (expr.kind) {
|
|
91
|
+
case "conditionalExpression":
|
|
92
|
+
return true;
|
|
93
|
+
case "identifierExpression":
|
|
94
|
+
return false;
|
|
95
|
+
case "qualifiedIdentifierExpression":
|
|
96
|
+
return nameMayPrintColon(expr.name);
|
|
97
|
+
case "typeReferenceExpression":
|
|
98
|
+
return typeMayPrintColon(expr.type);
|
|
99
|
+
case "parenthesizedExpression":
|
|
100
|
+
case "awaitExpression":
|
|
101
|
+
case "throwExpression":
|
|
102
|
+
case "suppressNullableWarningExpression":
|
|
103
|
+
case "argumentModifierExpression":
|
|
104
|
+
return expressionMayPrintColon(expr.expression);
|
|
105
|
+
case "prefixUnaryExpression":
|
|
106
|
+
case "postfixUnaryExpression":
|
|
107
|
+
return expressionMayPrintColon(expr.operand);
|
|
108
|
+
case "memberAccessExpression":
|
|
109
|
+
case "conditionalMemberAccessExpression":
|
|
110
|
+
return expressionMayPrintColon(expr.expression);
|
|
111
|
+
case "elementAccessExpression":
|
|
112
|
+
case "conditionalElementAccessExpression":
|
|
113
|
+
return (expressionMayPrintColon(expr.expression) ||
|
|
114
|
+
expr.arguments.some(expressionMayPrintColon));
|
|
115
|
+
case "implicitElementAccessExpression":
|
|
116
|
+
return expr.arguments.some(expressionMayPrintColon);
|
|
117
|
+
case "invocationExpression":
|
|
118
|
+
return (expressionMayPrintColon(expr.expression) ||
|
|
119
|
+
expr.arguments.some(expressionMayPrintColon) ||
|
|
120
|
+
expr.typeArguments?.some(typeMayPrintColon) === true);
|
|
121
|
+
case "objectCreationExpression":
|
|
122
|
+
return (typeMayPrintColon(expr.type) ||
|
|
123
|
+
expr.arguments.some(expressionMayPrintColon) ||
|
|
124
|
+
expr.initializer?.some(expressionMayPrintColon) === true);
|
|
125
|
+
case "arrayCreationExpression":
|
|
126
|
+
return (typeMayPrintColon(expr.elementType) ||
|
|
127
|
+
(expr.sizeExpression
|
|
128
|
+
? expressionMayPrintColon(expr.sizeExpression)
|
|
129
|
+
: false) ||
|
|
130
|
+
expr.initializer?.some(expressionMayPrintColon) === true);
|
|
131
|
+
case "stackAllocArrayCreationExpression":
|
|
132
|
+
return (typeMayPrintColon(expr.elementType) ||
|
|
133
|
+
expressionMayPrintColon(expr.sizeExpression));
|
|
134
|
+
case "assignmentExpression":
|
|
135
|
+
case "binaryExpression":
|
|
136
|
+
return (expressionMayPrintColon(expr.left) ||
|
|
137
|
+
expressionMayPrintColon(expr.right));
|
|
138
|
+
case "castExpression":
|
|
139
|
+
return (typeMayPrintColon(expr.type) || expressionMayPrintColon(expr.expression));
|
|
140
|
+
case "asExpression":
|
|
141
|
+
return (typeMayPrintColon(expr.type) || expressionMayPrintColon(expr.expression));
|
|
142
|
+
case "isExpression":
|
|
143
|
+
return (expressionMayPrintColon(expr.expression) ||
|
|
144
|
+
patternMayPrintColon(expr.pattern));
|
|
145
|
+
case "defaultExpression":
|
|
146
|
+
return expr.type ? typeMayPrintColon(expr.type) : false;
|
|
147
|
+
case "sizeOfExpression":
|
|
148
|
+
case "typeofExpression":
|
|
149
|
+
return typeMayPrintColon(expr.type);
|
|
150
|
+
case "lambdaExpression":
|
|
151
|
+
return expr.parameters.some((p) => p.type ? typeMayPrintColon(p.type) : false);
|
|
152
|
+
case "interpolatedStringExpression":
|
|
153
|
+
return expr.parts.some((part) => part.kind === "interpolation" &&
|
|
154
|
+
expressionMayPrintColon(part.expression));
|
|
155
|
+
case "switchExpression":
|
|
156
|
+
return (expressionMayPrintColon(expr.governingExpression) ||
|
|
157
|
+
expr.arms.some((arm) => patternMayPrintColon(arm.pattern) ||
|
|
158
|
+
(arm.whenClause
|
|
159
|
+
? expressionMayPrintColon(arm.whenClause)
|
|
160
|
+
: false) ||
|
|
161
|
+
expressionMayPrintColon(arm.expression)));
|
|
162
|
+
case "tupleExpression":
|
|
163
|
+
return expr.elements.some(expressionMayPrintColon);
|
|
164
|
+
case "nullLiteralExpression":
|
|
165
|
+
case "booleanLiteralExpression":
|
|
166
|
+
case "stringLiteralExpression":
|
|
167
|
+
case "charLiteralExpression":
|
|
168
|
+
case "numericLiteralExpression":
|
|
169
|
+
return false;
|
|
170
|
+
default: {
|
|
171
|
+
const exhaustive = expr;
|
|
172
|
+
throw new Error(`ICE: Unhandled expression AST kind '${exhaustive.kind}' in expressionMayPrintColon`);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
const needsPrefixUnarySeparator = (operatorToken, operand) => {
|
|
177
|
+
if (operatorToken !== "-" && operatorToken !== "+") {
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
const unwrapped = operand.kind === "parenthesizedExpression" ? operand.expression : operand;
|
|
181
|
+
return (unwrapped.kind === "prefixUnaryExpression" &&
|
|
182
|
+
unwrapped.operatorToken === operatorToken);
|
|
183
|
+
};
|
|
184
|
+
const printNumericLiteral = (expr) => {
|
|
185
|
+
const suffix = expr.suffix ?? "";
|
|
186
|
+
const hasRealParts = expr.fractionalPart !== undefined || expr.exponentDigits !== undefined;
|
|
187
|
+
if (hasRealParts) {
|
|
188
|
+
const fractional = expr.fractionalPart !== undefined ? `.${expr.fractionalPart}` : "";
|
|
189
|
+
const exponent = expr.exponentDigits !== undefined
|
|
190
|
+
? `e${expr.exponentSign ?? ""}${expr.exponentDigits}`
|
|
191
|
+
: "";
|
|
192
|
+
return `${expr.wholePart}${fractional}${exponent}${suffix}`;
|
|
193
|
+
}
|
|
194
|
+
switch (expr.base) {
|
|
195
|
+
case "decimal":
|
|
196
|
+
return `${expr.wholePart}${suffix}`;
|
|
197
|
+
case "hexadecimal":
|
|
198
|
+
return `0x${expr.wholePart}${suffix}`;
|
|
199
|
+
case "binary":
|
|
200
|
+
return `0b${expr.wholePart}${suffix}`;
|
|
201
|
+
default: {
|
|
202
|
+
const exhaustive = expr.base;
|
|
203
|
+
throw new Error(`ICE: Unhandled numeric literal base '${exhaustive}'`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
};
|
|
10
207
|
// ============================================================
|
|
11
208
|
// C# reserved keywords for identifier escaping
|
|
12
209
|
// ============================================================
|
|
@@ -115,21 +312,16 @@ const PREDEFINED_TYPE_KEYWORDS = new Set([
|
|
|
115
312
|
*/
|
|
116
313
|
const escapeIdentifier = (name) => CSHARP_KEYWORDS.has(name) ? `@${name}` : name;
|
|
117
314
|
/**
|
|
118
|
-
* Escape segments in a qualified name
|
|
119
|
-
* The "global::" prefix and predefined type keywords are preserved.
|
|
315
|
+
* Escape segments in a qualified name AST.
|
|
120
316
|
*/
|
|
121
317
|
const escapeQualifiedName = (name, preservePredefinedTypeKeywords = false) => {
|
|
122
|
-
const
|
|
123
|
-
const hasGlobal = name.startsWith(globalPrefix);
|
|
124
|
-
const body = hasGlobal ? name.slice(globalPrefix.length) : name;
|
|
125
|
-
const escaped = body
|
|
126
|
-
.split(".")
|
|
318
|
+
const escaped = [...name.segments]
|
|
127
319
|
.map((segment) => CSHARP_KEYWORDS.has(segment) &&
|
|
128
320
|
!(preservePredefinedTypeKeywords && PREDEFINED_TYPE_KEYWORDS.has(segment))
|
|
129
321
|
? `@${segment}`
|
|
130
322
|
: segment)
|
|
131
323
|
.join(".");
|
|
132
|
-
return
|
|
324
|
+
return name.aliasQualifier ? `${name.aliasQualifier}::${escaped}` : escaped;
|
|
133
325
|
};
|
|
134
326
|
// ============================================================
|
|
135
327
|
// Operator precedence for parenthesization
|
|
@@ -224,13 +416,20 @@ const getExpressionPrecedence = (expr) => {
|
|
|
224
416
|
case "awaitExpression":
|
|
225
417
|
return 14; // Await is at unary level
|
|
226
418
|
// Primary expressions (highest precedence)
|
|
227
|
-
case "
|
|
419
|
+
case "nullLiteralExpression":
|
|
420
|
+
case "booleanLiteralExpression":
|
|
421
|
+
case "stringLiteralExpression":
|
|
422
|
+
case "charLiteralExpression":
|
|
423
|
+
case "numericLiteralExpression":
|
|
228
424
|
case "identifierExpression":
|
|
425
|
+
case "qualifiedIdentifierExpression":
|
|
426
|
+
case "typeReferenceExpression":
|
|
229
427
|
case "parenthesizedExpression":
|
|
230
428
|
case "memberAccessExpression":
|
|
231
429
|
case "conditionalMemberAccessExpression":
|
|
232
430
|
case "elementAccessExpression":
|
|
233
431
|
case "conditionalElementAccessExpression":
|
|
432
|
+
case "implicitElementAccessExpression":
|
|
234
433
|
case "invocationExpression":
|
|
235
434
|
case "objectCreationExpression":
|
|
236
435
|
case "arrayCreationExpression":
|
|
@@ -289,8 +488,8 @@ const needsParensInBinary = (child, parentPrecedence, isRightOperand) => {
|
|
|
289
488
|
/**
|
|
290
489
|
* Wrap expression text in parens if needed for the given context.
|
|
291
490
|
*/
|
|
292
|
-
const parenthesizeIfNeeded = (expr, parentPrecedence, isRightOperand) => {
|
|
293
|
-
const text = printExpression(expr);
|
|
491
|
+
const parenthesizeIfNeeded = (expr, parentPrecedence, isRightOperand, indent) => {
|
|
492
|
+
const text = printExpression(expr, indent);
|
|
294
493
|
return needsParensInBinary(expr, parentPrecedence, isRightOperand)
|
|
295
494
|
? `(${text})`
|
|
296
495
|
: text;
|
|
@@ -303,6 +502,17 @@ export const printType = (type) => {
|
|
|
303
502
|
case "predefinedType":
|
|
304
503
|
return type.keyword;
|
|
305
504
|
case "identifierType": {
|
|
505
|
+
if (type.name.includes(".") || type.name.includes("::")) {
|
|
506
|
+
throw new Error(`ICE: Simple identifierType '${type.name}' contains qualification. Use qualifiedIdentifierType AST instead.`);
|
|
507
|
+
}
|
|
508
|
+
const name = escapeIdentifier(type.name);
|
|
509
|
+
if (!type.typeArguments || type.typeArguments.length === 0) {
|
|
510
|
+
return name;
|
|
511
|
+
}
|
|
512
|
+
const args = type.typeArguments.map(printType).join(", ");
|
|
513
|
+
return `${name}<${args}>`;
|
|
514
|
+
}
|
|
515
|
+
case "qualifiedIdentifierType": {
|
|
306
516
|
const name = escapeQualifiedName(type.name, true);
|
|
307
517
|
if (!type.typeArguments || type.typeArguments.length === 0) {
|
|
308
518
|
return name;
|
|
@@ -339,39 +549,68 @@ export const printType = (type) => {
|
|
|
339
549
|
// ============================================================
|
|
340
550
|
// Expression Printer
|
|
341
551
|
// ============================================================
|
|
342
|
-
export const printExpression = (expr) => {
|
|
552
|
+
export const printExpression = (expr, indent = "") => {
|
|
343
553
|
switch (expr.kind) {
|
|
344
|
-
case "
|
|
345
|
-
return
|
|
554
|
+
case "nullLiteralExpression":
|
|
555
|
+
return "null";
|
|
556
|
+
case "booleanLiteralExpression":
|
|
557
|
+
return expr.value ? "true" : "false";
|
|
558
|
+
case "stringLiteralExpression":
|
|
559
|
+
return `"${escapeCSharpStringLiteral(expr.value)}"`;
|
|
560
|
+
case "charLiteralExpression":
|
|
561
|
+
return `'${escapeCSharpCharLiteral(expr.value)}'`;
|
|
562
|
+
case "numericLiteralExpression":
|
|
563
|
+
return printNumericLiteral(expr);
|
|
346
564
|
case "identifierExpression":
|
|
565
|
+
if (expr.identifier.includes(".") || expr.identifier.includes("::")) {
|
|
566
|
+
throw new Error(`ICE: Simple identifierExpression '${expr.identifier}' contains qualification. Use qualifiedIdentifierExpression AST instead.`);
|
|
567
|
+
}
|
|
347
568
|
return escapeIdentifier(expr.identifier);
|
|
569
|
+
case "qualifiedIdentifierExpression":
|
|
570
|
+
return escapeQualifiedName(expr.name);
|
|
571
|
+
case "typeReferenceExpression":
|
|
572
|
+
return printType(expr.type);
|
|
348
573
|
case "parenthesizedExpression":
|
|
349
|
-
return `(${printExpression(expr.expression)})`;
|
|
574
|
+
return `(${printExpression(expr.expression, indent)})`;
|
|
350
575
|
case "memberAccessExpression":
|
|
351
|
-
return `${printPrimaryExpression(expr.expression)}.${escapeIdentifier(expr.memberName)}`;
|
|
576
|
+
return `${printPrimaryExpression(expr.expression, indent)}.${escapeIdentifier(expr.memberName)}`;
|
|
352
577
|
case "conditionalMemberAccessExpression":
|
|
353
|
-
return `${printPrimaryExpression(expr.expression)}?.${escapeIdentifier(expr.memberName)}`;
|
|
578
|
+
return `${printPrimaryExpression(expr.expression, indent)}?.${escapeIdentifier(expr.memberName)}`;
|
|
354
579
|
case "elementAccessExpression": {
|
|
355
|
-
const args = expr.arguments
|
|
356
|
-
|
|
580
|
+
const args = expr.arguments
|
|
581
|
+
.map((arg) => printExpression(arg, indent))
|
|
582
|
+
.join(", ");
|
|
583
|
+
return `${printPrimaryExpression(expr.expression, indent)}[${args}]`;
|
|
357
584
|
}
|
|
358
585
|
case "conditionalElementAccessExpression": {
|
|
359
|
-
const args = expr.arguments
|
|
360
|
-
|
|
586
|
+
const args = expr.arguments
|
|
587
|
+
.map((arg) => printExpression(arg, indent))
|
|
588
|
+
.join(", ");
|
|
589
|
+
return `${printPrimaryExpression(expr.expression, indent)}?[${args}]`;
|
|
590
|
+
}
|
|
591
|
+
case "implicitElementAccessExpression": {
|
|
592
|
+
const args = expr.arguments
|
|
593
|
+
.map((arg) => printExpression(arg, indent))
|
|
594
|
+
.join(", ");
|
|
595
|
+
return `[${args}]`;
|
|
361
596
|
}
|
|
362
597
|
case "invocationExpression": {
|
|
363
|
-
const callee = printPrimaryExpression(expr.expression);
|
|
598
|
+
const callee = printPrimaryExpression(expr.expression, indent);
|
|
364
599
|
const typeArgs = expr.typeArguments && expr.typeArguments.length > 0
|
|
365
600
|
? `<${expr.typeArguments.map(printType).join(", ")}>`
|
|
366
601
|
: "";
|
|
367
|
-
const args = expr.arguments
|
|
602
|
+
const args = expr.arguments
|
|
603
|
+
.map((arg) => printExpression(arg, indent))
|
|
604
|
+
.join(", ");
|
|
368
605
|
return `${callee}${typeArgs}(${args})`;
|
|
369
606
|
}
|
|
370
607
|
case "objectCreationExpression": {
|
|
371
608
|
const typeName = printType(expr.type);
|
|
372
|
-
const args = expr.arguments
|
|
609
|
+
const args = expr.arguments
|
|
610
|
+
.map((arg) => printExpression(arg, indent))
|
|
611
|
+
.join(", ");
|
|
373
612
|
const init = expr.initializer && expr.initializer.length > 0
|
|
374
|
-
? ` { ${expr.initializer.map(printExpression).join(", ")} }`
|
|
613
|
+
? ` { ${expr.initializer.map((item) => printExpression(item, indent)).join(", ")} }`
|
|
375
614
|
: "";
|
|
376
615
|
// Omit () when using collection/object initializer with no constructor args
|
|
377
616
|
// (C# allows `new List<T> { ... }` without parentheses)
|
|
@@ -385,58 +624,58 @@ export const printExpression = (expr) => {
|
|
|
385
624
|
const isImplicit = expr.elementType.kind === "varType";
|
|
386
625
|
const elemType = isImplicit ? "" : ` ${printType(expr.elementType)}`;
|
|
387
626
|
if (expr.initializer && expr.initializer.length > 0) {
|
|
388
|
-
const elems = expr.initializer
|
|
627
|
+
const elems = expr.initializer
|
|
628
|
+
.map((item) => printExpression(item, indent))
|
|
629
|
+
.join(", ");
|
|
389
630
|
if (expr.sizeExpression) {
|
|
390
|
-
return `new${elemType}[${printExpression(expr.sizeExpression)}] { ${elems} }`;
|
|
631
|
+
return `new${elemType}[${printExpression(expr.sizeExpression, indent)}] { ${elems} }`;
|
|
391
632
|
}
|
|
392
633
|
return `new${elemType}[] { ${elems} }`;
|
|
393
634
|
}
|
|
394
635
|
if (expr.sizeExpression) {
|
|
395
|
-
return `new${elemType}[${printExpression(expr.sizeExpression)}]`;
|
|
636
|
+
return `new${elemType}[${printExpression(expr.sizeExpression, indent)}]`;
|
|
396
637
|
}
|
|
397
638
|
return `new${elemType}[0]`;
|
|
398
639
|
}
|
|
399
640
|
case "stackAllocArrayCreationExpression":
|
|
400
|
-
return `stackalloc ${printType(expr.elementType)}[${printExpression(expr.sizeExpression)}]`;
|
|
641
|
+
return `stackalloc ${printType(expr.elementType)}[${printExpression(expr.sizeExpression, indent)}]`;
|
|
401
642
|
case "assignmentExpression": {
|
|
402
|
-
const left = printExpression(expr.left);
|
|
403
|
-
const right = printExpression(expr.right);
|
|
643
|
+
const left = printExpression(expr.left, indent);
|
|
644
|
+
const right = printExpression(expr.right, indent);
|
|
404
645
|
return `${left} ${expr.operatorToken} ${right}`;
|
|
405
646
|
}
|
|
406
647
|
case "binaryExpression": {
|
|
407
648
|
const prec = getOperatorPrecedence(expr.operatorToken);
|
|
408
|
-
const left = parenthesizeIfNeeded(expr.left, prec, false);
|
|
409
|
-
const right = parenthesizeIfNeeded(expr.right, prec, true);
|
|
649
|
+
const left = parenthesizeIfNeeded(expr.left, prec, false, indent);
|
|
650
|
+
const right = parenthesizeIfNeeded(expr.right, prec, true, indent);
|
|
410
651
|
return `${left} ${expr.operatorToken} ${right}`;
|
|
411
652
|
}
|
|
412
653
|
case "prefixUnaryExpression": {
|
|
413
|
-
const operand = printUnaryOperand(expr.operand, true);
|
|
414
|
-
|
|
415
|
-
if ((expr.operatorToken === "-" && operand.startsWith("-")) ||
|
|
416
|
-
(expr.operatorToken === "+" && operand.startsWith("+"))) {
|
|
654
|
+
const operand = printUnaryOperand(expr.operand, true, indent);
|
|
655
|
+
if (needsPrefixUnarySeparator(expr.operatorToken, expr.operand)) {
|
|
417
656
|
return `${expr.operatorToken} ${operand}`;
|
|
418
657
|
}
|
|
419
658
|
return `${expr.operatorToken}${operand}`;
|
|
420
659
|
}
|
|
421
660
|
case "postfixUnaryExpression":
|
|
422
|
-
return `${printUnaryOperand(expr.operand, false)}${expr.operatorToken}`;
|
|
661
|
+
return `${printUnaryOperand(expr.operand, false, indent)}${expr.operatorToken}`;
|
|
423
662
|
case "conditionalExpression": {
|
|
424
|
-
const cond = printExpression(expr.condition);
|
|
425
|
-
const whenTrue = printExpression(expr.whenTrue);
|
|
426
|
-
const whenFalse = printExpression(expr.whenFalse);
|
|
663
|
+
const cond = printExpression(expr.condition, indent);
|
|
664
|
+
const whenTrue = printExpression(expr.whenTrue, indent);
|
|
665
|
+
const whenFalse = printExpression(expr.whenFalse, indent);
|
|
427
666
|
return `${cond} ? ${whenTrue} : ${whenFalse}`;
|
|
428
667
|
}
|
|
429
668
|
case "castExpression": {
|
|
430
669
|
const typeName = printType(expr.type);
|
|
431
|
-
const operand = printCastOperand(expr.expression);
|
|
670
|
+
const operand = printCastOperand(expr.expression, indent);
|
|
432
671
|
return `(${typeName})${operand}`;
|
|
433
672
|
}
|
|
434
673
|
case "asExpression": {
|
|
435
|
-
const inner = printExpression(expr.expression);
|
|
674
|
+
const inner = printExpression(expr.expression, indent);
|
|
436
675
|
return `${inner} as ${printType(expr.type)}`;
|
|
437
676
|
}
|
|
438
677
|
case "isExpression": {
|
|
439
|
-
const inner = printExpression(expr.expression);
|
|
678
|
+
const inner = printExpression(expr.expression, indent);
|
|
440
679
|
const pattern = printPattern(expr.pattern);
|
|
441
680
|
return `${inner} is ${pattern}`;
|
|
442
681
|
}
|
|
@@ -445,23 +684,25 @@ export const printExpression = (expr) => {
|
|
|
445
684
|
case "sizeOfExpression":
|
|
446
685
|
return `sizeof(${printType(expr.type)})`;
|
|
447
686
|
case "awaitExpression":
|
|
448
|
-
return `await ${printUnaryOperand(expr.expression, true)}`;
|
|
687
|
+
return `await ${printUnaryOperand(expr.expression, true, indent)}`;
|
|
449
688
|
case "lambdaExpression":
|
|
450
|
-
return printLambdaExpression(expr);
|
|
689
|
+
return printLambdaExpression(expr, indent);
|
|
451
690
|
case "interpolatedStringExpression":
|
|
452
|
-
return printInterpolatedString(expr.parts);
|
|
691
|
+
return printInterpolatedString(expr.parts, indent);
|
|
453
692
|
case "throwExpression":
|
|
454
|
-
return `throw ${printExpression(expr.expression)}`;
|
|
693
|
+
return `throw ${printExpression(expr.expression, indent)}`;
|
|
455
694
|
case "suppressNullableWarningExpression":
|
|
456
|
-
return `${printPrimaryExpression(expr.expression)}!`;
|
|
695
|
+
return `${printPrimaryExpression(expr.expression, indent)}!`;
|
|
457
696
|
case "typeofExpression":
|
|
458
697
|
return `typeof(${printType(expr.type)})`;
|
|
459
698
|
case "switchExpression":
|
|
460
|
-
return printSwitchExpression(expr);
|
|
699
|
+
return printSwitchExpression(expr, indent);
|
|
461
700
|
case "argumentModifierExpression":
|
|
462
|
-
return `${expr.modifier} ${printExpression(expr.expression)}`;
|
|
701
|
+
return `${expr.modifier} ${printExpression(expr.expression, indent)}`;
|
|
463
702
|
case "tupleExpression": {
|
|
464
|
-
const elems = expr.elements
|
|
703
|
+
const elems = expr.elements
|
|
704
|
+
.map((element) => printExpression(element, indent))
|
|
705
|
+
.join(", ");
|
|
465
706
|
return `(${elems})`;
|
|
466
707
|
}
|
|
467
708
|
default: {
|
|
@@ -475,16 +716,21 @@ export const printExpression = (expr) => {
|
|
|
475
716
|
* (before `.member`, `[index]`, `(args)`, etc.).
|
|
476
717
|
* Wraps in parens if needed.
|
|
477
718
|
*/
|
|
478
|
-
const printPrimaryExpression = (expr) => {
|
|
479
|
-
const text = printExpression(expr);
|
|
719
|
+
const printPrimaryExpression = (expr, indent) => {
|
|
720
|
+
const text = printExpression(expr, indent);
|
|
480
721
|
const prec = getExpressionPrecedence(expr);
|
|
481
722
|
// Primary position requires precedence >= 15 (postfix and primary)
|
|
482
723
|
// or the expression is already a parenthesized/literal/identifier
|
|
483
724
|
if (prec >= 15)
|
|
484
725
|
return text;
|
|
485
726
|
if (expr.kind === "parenthesizedExpression" ||
|
|
486
|
-
expr.kind === "
|
|
727
|
+
expr.kind === "nullLiteralExpression" ||
|
|
728
|
+
expr.kind === "booleanLiteralExpression" ||
|
|
729
|
+
expr.kind === "stringLiteralExpression" ||
|
|
730
|
+
expr.kind === "charLiteralExpression" ||
|
|
731
|
+
expr.kind === "numericLiteralExpression" ||
|
|
487
732
|
expr.kind === "identifierExpression" ||
|
|
733
|
+
expr.kind === "qualifiedIdentifierExpression" ||
|
|
488
734
|
expr.kind === "defaultExpression" ||
|
|
489
735
|
expr.kind === "sizeOfExpression" ||
|
|
490
736
|
expr.kind === "typeofExpression" ||
|
|
@@ -498,8 +744,8 @@ const printPrimaryExpression = (expr) => {
|
|
|
498
744
|
/**
|
|
499
745
|
* Print an expression that appears as a unary operand.
|
|
500
746
|
*/
|
|
501
|
-
const printUnaryOperand = (expr, isPrefix) => {
|
|
502
|
-
const text = printExpression(expr);
|
|
747
|
+
const printUnaryOperand = (expr, isPrefix, indent) => {
|
|
748
|
+
const text = printExpression(expr, indent);
|
|
503
749
|
const prec = getExpressionPrecedence(expr);
|
|
504
750
|
if (isPrefix) {
|
|
505
751
|
// Prefix unary needs operand to be at least unary precedence
|
|
@@ -512,8 +758,8 @@ const printUnaryOperand = (expr, isPrefix) => {
|
|
|
512
758
|
* Print an expression that appears as a cast operand.
|
|
513
759
|
* Special rules: unary minus after cast needs parens to avoid ambiguity.
|
|
514
760
|
*/
|
|
515
|
-
const printCastOperand = (expr) => {
|
|
516
|
-
const text = printExpression(expr);
|
|
761
|
+
const printCastOperand = (expr, indent) => {
|
|
762
|
+
const text = printExpression(expr, indent);
|
|
517
763
|
// Cast operand needs at least unary precedence
|
|
518
764
|
if (getExpressionPrecedence(expr) < 14) {
|
|
519
765
|
return `(${text})`;
|
|
@@ -523,26 +769,16 @@ const printCastOperand = (expr) => {
|
|
|
523
769
|
if (expr.kind === "prefixUnaryExpression" && expr.operatorToken === "-") {
|
|
524
770
|
return `(${text})`;
|
|
525
771
|
}
|
|
526
|
-
if (expr.kind === "literalExpression" && text.startsWith("-")) {
|
|
527
|
-
return `(${text})`;
|
|
528
|
-
}
|
|
529
772
|
return text;
|
|
530
773
|
};
|
|
531
|
-
const printLambdaExpression = (expr) => {
|
|
774
|
+
const printLambdaExpression = (expr, indent) => {
|
|
532
775
|
const asyncPrefix = expr.isAsync ? "async " : "";
|
|
533
776
|
const params = printLambdaParameters(expr.parameters);
|
|
534
777
|
if (expr.body.kind === "blockStatement") {
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
return `${asyncPrefix}${params} =>\n${printStatementFlatBlock(expr.body, expr.bodyIndent)}`;
|
|
538
|
-
}
|
|
539
|
-
// Inline single-line block body: () => { stmt1; stmt2; }
|
|
540
|
-
const stmts = expr.body.statements
|
|
541
|
-
.map((s) => printStatement(s, ""))
|
|
542
|
-
.join(" ");
|
|
543
|
-
return `${asyncPrefix}${params} => { ${stmts} }`;
|
|
778
|
+
const bodyIndent = `${indent} `;
|
|
779
|
+
return `${asyncPrefix}${params} =>\n${printStatementFlatBlock(expr.body, bodyIndent)}`;
|
|
544
780
|
}
|
|
545
|
-
return `${asyncPrefix}${params} => ${printExpression(expr.body)}`;
|
|
781
|
+
return `${asyncPrefix}${params} => ${printExpression(expr.body, indent)}`;
|
|
546
782
|
};
|
|
547
783
|
const printLambdaParameters = (params) => {
|
|
548
784
|
const sole = params.length === 1 ? params[0] : undefined;
|
|
@@ -557,16 +793,15 @@ const printLambdaParameters = (params) => {
|
|
|
557
793
|
});
|
|
558
794
|
return `(${parts.join(", ")})`;
|
|
559
795
|
};
|
|
560
|
-
const printInterpolatedString = (parts) => {
|
|
796
|
+
const printInterpolatedString = (parts, indent) => {
|
|
561
797
|
const inner = parts
|
|
562
798
|
.map((part) => {
|
|
563
799
|
if (part.kind === "text")
|
|
564
800
|
return part.text;
|
|
565
|
-
const exprText = printExpression(part.expression);
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
const safeText = exprText.includes(":") ? `(${exprText})` : exprText;
|
|
801
|
+
const exprText = printExpression(part.expression, indent);
|
|
802
|
+
const safeText = expressionMayPrintColon(part.expression)
|
|
803
|
+
? `(${exprText})`
|
|
804
|
+
: exprText;
|
|
570
805
|
return part.formatClause
|
|
571
806
|
? `{${safeText}:${part.formatClause}}`
|
|
572
807
|
: `{${safeText}}`;
|
|
@@ -574,17 +809,19 @@ const printInterpolatedString = (parts) => {
|
|
|
574
809
|
.join("");
|
|
575
810
|
return `$"${inner}"`;
|
|
576
811
|
};
|
|
577
|
-
const printSwitchExpression = (expr) => {
|
|
578
|
-
const gov = printExpression(expr.governingExpression);
|
|
579
|
-
const arms = expr.arms
|
|
812
|
+
const printSwitchExpression = (expr, indent) => {
|
|
813
|
+
const gov = printExpression(expr.governingExpression, indent);
|
|
814
|
+
const arms = expr.arms
|
|
815
|
+
.map((arm) => printSwitchExpressionArm(arm, indent))
|
|
816
|
+
.join(", ");
|
|
580
817
|
return `${gov} switch { ${arms} }`;
|
|
581
818
|
};
|
|
582
|
-
const printSwitchExpressionArm = (arm) => {
|
|
819
|
+
const printSwitchExpressionArm = (arm, indent) => {
|
|
583
820
|
const pattern = printPattern(arm.pattern);
|
|
584
821
|
const whenClause = arm.whenClause
|
|
585
|
-
? ` when ${printExpression(arm.whenClause)}`
|
|
822
|
+
? ` when ${printExpression(arm.whenClause, indent)}`
|
|
586
823
|
: "";
|
|
587
|
-
const result = printExpression(arm.expression);
|
|
824
|
+
const result = printExpression(arm.expression, indent);
|
|
588
825
|
return `${pattern}${whenClause} => ${result}`;
|
|
589
826
|
};
|
|
590
827
|
// ============================================================
|
|
@@ -622,7 +859,7 @@ export const printStatement = (stmt, indent) => {
|
|
|
622
859
|
const typeStr = printType(stmt.type);
|
|
623
860
|
const decls = stmt.declarators
|
|
624
861
|
.map((d) => d.initializer
|
|
625
|
-
? `${escapeIdentifier(d.name)} = ${printExpression(d.initializer)}`
|
|
862
|
+
? `${escapeIdentifier(d.name)} = ${printExpression(d.initializer, indent)}`
|
|
626
863
|
: escapeIdentifier(d.name))
|
|
627
864
|
.join(", ");
|
|
628
865
|
return `${indent}${mods}${typeStr} ${decls};`;
|
|
@@ -638,11 +875,11 @@ export const printStatement = (stmt, indent) => {
|
|
|
638
875
|
return `${indent}${mods}${ret} ${escapeIdentifier(stmt.name)}${typeParams}(${params})\n${body}`;
|
|
639
876
|
}
|
|
640
877
|
case "expressionStatement":
|
|
641
|
-
return `${indent}${printExpression(stmt.expression)};`;
|
|
878
|
+
return `${indent}${printExpression(stmt.expression, indent)};`;
|
|
642
879
|
case "ifStatement":
|
|
643
880
|
return printIfStatement(stmt, indent);
|
|
644
881
|
case "whileStatement": {
|
|
645
|
-
const cond = printExpression(stmt.condition);
|
|
882
|
+
const cond = printExpression(stmt.condition, indent);
|
|
646
883
|
const body = printStatement(stmt.body, indent);
|
|
647
884
|
return `${indent}while (${cond})\n${body}`;
|
|
648
885
|
}
|
|
@@ -652,7 +889,7 @@ export const printStatement = (stmt, indent) => {
|
|
|
652
889
|
const awaitStr = stmt.isAwait ? "await " : "";
|
|
653
890
|
const typeStr = printType(stmt.type);
|
|
654
891
|
const ident = escapeIdentifier(stmt.identifier);
|
|
655
|
-
const collection = printExpression(stmt.expression);
|
|
892
|
+
const collection = printExpression(stmt.expression, indent);
|
|
656
893
|
const body = printStatement(stmt.body, indent);
|
|
657
894
|
return `${indent}${awaitStr}foreach (${typeStr} ${ident} in ${collection})\n${body}`;
|
|
658
895
|
}
|
|
@@ -662,11 +899,11 @@ export const printStatement = (stmt, indent) => {
|
|
|
662
899
|
return printTryStatement(stmt, indent);
|
|
663
900
|
case "throwStatement":
|
|
664
901
|
return stmt.expression
|
|
665
|
-
? `${indent}throw ${printExpression(stmt.expression)};`
|
|
902
|
+
? `${indent}throw ${printExpression(stmt.expression, indent)};`
|
|
666
903
|
: `${indent}throw;`;
|
|
667
904
|
case "returnStatement":
|
|
668
905
|
return stmt.expression
|
|
669
|
-
? `${indent}return ${printExpression(stmt.expression)};`
|
|
906
|
+
? `${indent}return ${printExpression(stmt.expression, indent)};`
|
|
670
907
|
: `${indent}return;`;
|
|
671
908
|
case "breakStatement":
|
|
672
909
|
return `${indent}break;`;
|
|
@@ -679,7 +916,7 @@ export const printStatement = (stmt, indent) => {
|
|
|
679
916
|
return `${indent}yield break;`;
|
|
680
917
|
}
|
|
681
918
|
return stmt.expression
|
|
682
|
-
? `${indent}yield return ${printExpression(stmt.expression)};`
|
|
919
|
+
? `${indent}yield return ${printExpression(stmt.expression, indent)};`
|
|
683
920
|
: `${indent}yield return;`;
|
|
684
921
|
default: {
|
|
685
922
|
const exhaustiveCheck = stmt;
|
|
@@ -695,7 +932,7 @@ const printBlockStatement = (block, indent) => {
|
|
|
695
932
|
return `${indent}{\n${stmts}\n${indent}}`;
|
|
696
933
|
};
|
|
697
934
|
const printIfStatement = (stmt, indent) => {
|
|
698
|
-
const cond = printExpression(stmt.condition);
|
|
935
|
+
const cond = printExpression(stmt.condition, indent);
|
|
699
936
|
const thenBody = printStatement(stmt.thenStatement, indent);
|
|
700
937
|
if (!stmt.elseStatement) {
|
|
701
938
|
return `${indent}if (${cond})\n${thenBody}`;
|
|
@@ -717,27 +954,27 @@ const printForStatement = (stmt, indent) => {
|
|
|
717
954
|
const typeStr = printType(stmt.declaration.type);
|
|
718
955
|
const decls = stmt.declaration.declarators
|
|
719
956
|
.map((d) => d.initializer
|
|
720
|
-
? `${escapeIdentifier(d.name)} = ${printExpression(d.initializer)}`
|
|
957
|
+
? `${escapeIdentifier(d.name)} = ${printExpression(d.initializer, indent)}`
|
|
721
958
|
: escapeIdentifier(d.name))
|
|
722
959
|
.join(", ");
|
|
723
960
|
parts.push(`${typeStr} ${decls}`);
|
|
724
961
|
}
|
|
725
962
|
else if (stmt.initializers && stmt.initializers.length > 0) {
|
|
726
|
-
parts.push(stmt.initializers.map(printExpression).join(", "));
|
|
963
|
+
parts.push(stmt.initializers.map((expr) => printExpression(expr, indent)).join(", "));
|
|
727
964
|
}
|
|
728
965
|
else {
|
|
729
966
|
parts.push("");
|
|
730
967
|
}
|
|
731
968
|
// Condition
|
|
732
|
-
parts.push(stmt.condition ? printExpression(stmt.condition) : "");
|
|
969
|
+
parts.push(stmt.condition ? printExpression(stmt.condition, indent) : "");
|
|
733
970
|
// Incrementors
|
|
734
|
-
parts.push(stmt.incrementors.map(printExpression).join(", "));
|
|
971
|
+
parts.push(stmt.incrementors.map((expr) => printExpression(expr, indent)).join(", "));
|
|
735
972
|
const header = parts.join("; ");
|
|
736
973
|
const body = printStatement(stmt.body, indent);
|
|
737
974
|
return `${indent}for (${header})\n${body}`;
|
|
738
975
|
};
|
|
739
976
|
const printSwitchStatement = (stmt, indent) => {
|
|
740
|
-
const expr = printExpression(stmt.expression);
|
|
977
|
+
const expr = printExpression(stmt.expression, indent);
|
|
741
978
|
const innerIndent = indent + " ";
|
|
742
979
|
const sections = stmt.sections
|
|
743
980
|
.map((s) => printSwitchSection(s, innerIndent))
|
|
@@ -757,11 +994,11 @@ const printSwitchSection = (section, indent) => {
|
|
|
757
994
|
const printSwitchLabel = (label, indent) => {
|
|
758
995
|
switch (label.kind) {
|
|
759
996
|
case "caseSwitchLabel":
|
|
760
|
-
return `${indent}case ${printExpression(label.value)}:`;
|
|
997
|
+
return `${indent}case ${printExpression(label.value, indent)}:`;
|
|
761
998
|
case "casePatternSwitchLabel": {
|
|
762
999
|
const pattern = printPattern(label.pattern);
|
|
763
1000
|
const when = label.whenClause
|
|
764
|
-
? ` when ${printExpression(label.whenClause)}`
|
|
1001
|
+
? ` when ${printExpression(label.whenClause, indent)}`
|
|
765
1002
|
: "";
|
|
766
1003
|
return `${indent}case ${pattern}${when}:`;
|
|
767
1004
|
}
|
|
@@ -789,7 +1026,7 @@ const printCatchClause = (clause, indent) => {
|
|
|
789
1026
|
? ` ${escapeIdentifier(clause.identifier)}`
|
|
790
1027
|
: "";
|
|
791
1028
|
const filter = clause.filter
|
|
792
|
-
? ` when (${printExpression(clause.filter)})`
|
|
1029
|
+
? ` when (${printExpression(clause.filter, indent)})`
|
|
793
1030
|
: "";
|
|
794
1031
|
return `${indent}catch (${typeName}${ident})${filter}\n${body}`;
|
|
795
1032
|
};
|
|
@@ -799,7 +1036,7 @@ export const printParameter = (param) => {
|
|
|
799
1036
|
.map((a) => {
|
|
800
1037
|
const targetPrefix = a.target ? `${a.target}: ` : "";
|
|
801
1038
|
const args = a.arguments && a.arguments.length > 0
|
|
802
|
-
? `(${a.arguments.map(printExpression).join(", ")})`
|
|
1039
|
+
? `(${a.arguments.map((arg) => printExpression(arg)).join(", ")})`
|
|
803
1040
|
: "";
|
|
804
1041
|
return `[${targetPrefix}${printType(a.type)}${args}]`;
|
|
805
1042
|
})
|
|
@@ -826,7 +1063,7 @@ export const printMember = (member, indent) => {
|
|
|
826
1063
|
const typeName = printType(member.type);
|
|
827
1064
|
const name = escapeIdentifier(member.name);
|
|
828
1065
|
const init = member.initializer
|
|
829
|
-
? ` = ${printExpression(member.initializer)}`
|
|
1066
|
+
? ` = ${printExpression(member.initializer, indent)}`
|
|
830
1067
|
: "";
|
|
831
1068
|
return `${attrs}${indent}${mods}${typeName} ${name}${init};`;
|
|
832
1069
|
}
|
|
@@ -844,7 +1081,7 @@ export const printMember = (member, indent) => {
|
|
|
844
1081
|
: "";
|
|
845
1082
|
const accessors = ` { ${getStr}${setStr}}`;
|
|
846
1083
|
const init = member.initializer
|
|
847
|
-
? ` = ${printExpression(member.initializer)};`
|
|
1084
|
+
? ` = ${printExpression(member.initializer, indent)};`
|
|
848
1085
|
: "";
|
|
849
1086
|
return `${attrs}${indent}${mods}${typeName} ${name}${accessors}${init}`;
|
|
850
1087
|
}
|
|
@@ -873,7 +1110,7 @@ export const printMember = (member, indent) => {
|
|
|
873
1110
|
const params = member.parameters.map(printParameter).join(", ");
|
|
874
1111
|
const constraints = printConstraints(member.constraints, indent);
|
|
875
1112
|
if (member.expressionBody) {
|
|
876
|
-
return `${attrs}${indent}${mods}${ret} ${escapeIdentifier(member.name)}${typeParams}(${params})${constraints} => ${printExpression(member.expressionBody)};`;
|
|
1113
|
+
return `${attrs}${indent}${mods}${ret} ${escapeIdentifier(member.name)}${typeParams}(${params})${constraints} => ${printExpression(member.expressionBody, indent)};`;
|
|
877
1114
|
}
|
|
878
1115
|
if (member.body) {
|
|
879
1116
|
return `${attrs}${indent}${mods}${ret} ${escapeIdentifier(member.name)}${typeParams}(${params})${constraints}\n${printBlockStatement(member.body, indent)}`;
|
|
@@ -886,7 +1123,7 @@ export const printMember = (member, indent) => {
|
|
|
886
1123
|
const mods = member.modifiers.length > 0 ? `${member.modifiers.join(" ")} ` : "";
|
|
887
1124
|
const params = member.parameters.map(printParameter).join(", ");
|
|
888
1125
|
const baseCall = member.baseArguments !== undefined
|
|
889
|
-
? ` : base(${member.baseArguments.map(printExpression).join(", ")})`
|
|
1126
|
+
? ` : base(${member.baseArguments.map((arg) => printExpression(arg, indent)).join(", ")})`
|
|
890
1127
|
: "";
|
|
891
1128
|
return `${attrs}${indent}${mods}${escapeIdentifier(member.name)}(${params})${baseCall}\n${printBlockStatement(member.body, indent)}`;
|
|
892
1129
|
}
|
|
@@ -944,7 +1181,7 @@ export const printTypeDeclaration = (decl, indent) => {
|
|
|
944
1181
|
}
|
|
945
1182
|
};
|
|
946
1183
|
const printEnumMember = (member, indent) => member.value
|
|
947
|
-
? `${indent}${escapeIdentifier(member.name)} = ${printExpression(member.value)}`
|
|
1184
|
+
? `${indent}${escapeIdentifier(member.name)} = ${printExpression(member.value, indent)}`
|
|
948
1185
|
: `${indent}${escapeIdentifier(member.name)}`;
|
|
949
1186
|
const printTypeParameters = (typeParams) => {
|
|
950
1187
|
if (!typeParams || typeParams.length === 0)
|
|
@@ -983,7 +1220,7 @@ export const printAttributes = (attrs, indent) => {
|
|
|
983
1220
|
.map((a) => {
|
|
984
1221
|
const targetPrefix = a.target ? `${a.target}: ` : "";
|
|
985
1222
|
const args = a.arguments && a.arguments.length > 0
|
|
986
|
-
? `(${a.arguments.map(printExpression).join(", ")})`
|
|
1223
|
+
? `(${a.arguments.map((arg) => printExpression(arg, indent)).join(", ")})`
|
|
987
1224
|
: "";
|
|
988
1225
|
return `${indent}[${targetPrefix}${printType(a.type)}${args}]\n`;
|
|
989
1226
|
})
|
|
@@ -994,8 +1231,8 @@ export const printAttributes = (attrs, indent) => {
|
|
|
994
1231
|
// ============================================================
|
|
995
1232
|
export const printCompilationUnit = (unit) => {
|
|
996
1233
|
const parts = [];
|
|
997
|
-
if (unit.
|
|
998
|
-
parts.push(unit.
|
|
1234
|
+
if (unit.leadingTrivia && unit.leadingTrivia.length > 0) {
|
|
1235
|
+
parts.push(unit.leadingTrivia.map(printTrivia).join("\n"));
|
|
999
1236
|
}
|
|
1000
1237
|
const usings = unit.usings
|
|
1001
1238
|
.map((u) => `using ${escapeQualifiedName(u.namespace, false)};`)
|
|
@@ -1049,7 +1286,7 @@ export const printStatementFlatBlock = (stmt, indent) => {
|
|
|
1049
1286
|
return `${indent}{\n${inner}\n${indent}}`;
|
|
1050
1287
|
}
|
|
1051
1288
|
case "ifStatement": {
|
|
1052
|
-
const cond = printExpression(stmt.condition);
|
|
1289
|
+
const cond = printExpression(stmt.condition, indent);
|
|
1053
1290
|
const thenBody = printStatementFlatBlock(stmt.thenStatement, bodyIndent);
|
|
1054
1291
|
if (!stmt.elseStatement) {
|
|
1055
1292
|
return `${indent}if (${cond})\n${thenBody}`;
|
|
@@ -1064,7 +1301,7 @@ export const printStatementFlatBlock = (stmt, indent) => {
|
|
|
1064
1301
|
return `${indent}if (${cond})\n${thenBody}\n${indent}else\n${elseBody}`;
|
|
1065
1302
|
}
|
|
1066
1303
|
case "whileStatement": {
|
|
1067
|
-
const cond = printExpression(stmt.condition);
|
|
1304
|
+
const cond = printExpression(stmt.condition, indent);
|
|
1068
1305
|
const body = printStatementFlatBlock(stmt.body, bodyIndent);
|
|
1069
1306
|
return `${indent}while (${cond})\n${body}`;
|
|
1070
1307
|
}
|
|
@@ -1074,19 +1311,23 @@ export const printStatementFlatBlock = (stmt, indent) => {
|
|
|
1074
1311
|
const typeStr = printType(stmt.declaration.type);
|
|
1075
1312
|
const decls = stmt.declaration.declarators
|
|
1076
1313
|
.map((d) => d.initializer
|
|
1077
|
-
? `${escapeIdentifier(d.name)} = ${printExpression(d.initializer)}`
|
|
1314
|
+
? `${escapeIdentifier(d.name)} = ${printExpression(d.initializer, indent)}`
|
|
1078
1315
|
: escapeIdentifier(d.name))
|
|
1079
1316
|
.join(", ");
|
|
1080
1317
|
parts.push(`${typeStr} ${decls}`);
|
|
1081
1318
|
}
|
|
1082
1319
|
else if (stmt.initializers && stmt.initializers.length > 0) {
|
|
1083
|
-
parts.push(stmt.initializers
|
|
1320
|
+
parts.push(stmt.initializers
|
|
1321
|
+
.map((expr) => printExpression(expr, indent))
|
|
1322
|
+
.join(", "));
|
|
1084
1323
|
}
|
|
1085
1324
|
else {
|
|
1086
1325
|
parts.push("");
|
|
1087
1326
|
}
|
|
1088
|
-
parts.push(stmt.condition ? printExpression(stmt.condition) : "");
|
|
1089
|
-
parts.push(stmt.incrementors
|
|
1327
|
+
parts.push(stmt.condition ? printExpression(stmt.condition, indent) : "");
|
|
1328
|
+
parts.push(stmt.incrementors
|
|
1329
|
+
.map((expr) => printExpression(expr, indent))
|
|
1330
|
+
.join(", "));
|
|
1090
1331
|
const header = parts.join("; ");
|
|
1091
1332
|
const body = printStatementFlatBlock(stmt.body, bodyIndent);
|
|
1092
1333
|
return `${indent}for (${header})\n${body}`;
|
|
@@ -1095,12 +1336,12 @@ export const printStatementFlatBlock = (stmt, indent) => {
|
|
|
1095
1336
|
const awaitStr = stmt.isAwait ? "await " : "";
|
|
1096
1337
|
const typeStr = printType(stmt.type);
|
|
1097
1338
|
const ident = escapeIdentifier(stmt.identifier);
|
|
1098
|
-
const collection = printExpression(stmt.expression);
|
|
1339
|
+
const collection = printExpression(stmt.expression, indent);
|
|
1099
1340
|
const body = printStatementFlatBlock(stmt.body, bodyIndent);
|
|
1100
1341
|
return `${indent}${awaitStr}foreach (${typeStr} ${ident} in ${collection})\n${body}`;
|
|
1101
1342
|
}
|
|
1102
1343
|
case "switchStatement": {
|
|
1103
|
-
const expr = printExpression(stmt.expression);
|
|
1344
|
+
const expr = printExpression(stmt.expression, indent);
|
|
1104
1345
|
const sections = stmt.sections
|
|
1105
1346
|
.map((s) => {
|
|
1106
1347
|
const labels = s.labels
|
|
@@ -1129,7 +1370,9 @@ export const printStatementFlatBlock = (stmt, indent) => {
|
|
|
1129
1370
|
const ident = c.identifier
|
|
1130
1371
|
? ` ${escapeIdentifier(c.identifier)}`
|
|
1131
1372
|
: "";
|
|
1132
|
-
const filter = c.filter
|
|
1373
|
+
const filter = c.filter
|
|
1374
|
+
? ` when (${printExpression(c.filter, indent)})`
|
|
1375
|
+
: "";
|
|
1133
1376
|
return `${indent}catch (${typeName}${ident})${filter}\n${catchBody}`;
|
|
1134
1377
|
})
|
|
1135
1378
|
.join("\n");
|