@tsonic/emitter 0.0.72 → 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.
Files changed (207) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/adapter-generator.d.ts.map +1 -1
  3. package/dist/adapter-generator.js +2 -1
  4. package/dist/adapter-generator.js.map +1 -1
  5. package/dist/constants.d.ts +3 -2
  6. package/dist/constants.d.ts.map +1 -1
  7. package/dist/constants.js +15 -6
  8. package/dist/constants.js.map +1 -1
  9. package/dist/core/format/attributes.d.ts.map +1 -1
  10. package/dist/core/format/attributes.js +5 -56
  11. package/dist/core/format/attributes.js.map +1 -1
  12. package/dist/core/format/attributes.test.js +1 -1
  13. package/dist/core/format/attributes.test.js.map +1 -1
  14. package/dist/core/format/backend-ast/builders.d.ts +13 -0
  15. package/dist/core/format/backend-ast/builders.d.ts.map +1 -0
  16. package/dist/core/format/backend-ast/builders.js +169 -0
  17. package/dist/core/format/backend-ast/builders.js.map +1 -0
  18. package/dist/core/format/backend-ast/builders.test.d.ts +2 -0
  19. package/dist/core/format/backend-ast/builders.test.d.ts.map +1 -0
  20. package/dist/core/format/backend-ast/builders.test.js +258 -0
  21. package/dist/core/format/backend-ast/builders.test.js.map +1 -0
  22. package/dist/core/format/backend-ast/index.d.ts +3 -2
  23. package/dist/core/format/backend-ast/index.d.ts.map +1 -1
  24. package/dist/core/format/backend-ast/index.js +2 -1
  25. package/dist/core/format/backend-ast/index.js.map +1 -1
  26. package/dist/core/format/backend-ast/invariants.test.d.ts +2 -0
  27. package/dist/core/format/backend-ast/invariants.test.d.ts.map +1 -0
  28. package/dist/core/format/backend-ast/invariants.test.js +72 -0
  29. package/dist/core/format/backend-ast/invariants.test.js.map +1 -0
  30. package/dist/core/format/backend-ast/printer.d.ts +1 -1
  31. package/dist/core/format/backend-ast/printer.d.ts.map +1 -1
  32. package/dist/core/format/backend-ast/printer.js +362 -119
  33. package/dist/core/format/backend-ast/printer.js.map +1 -1
  34. package/dist/core/format/backend-ast/printer.test.d.ts +2 -0
  35. package/dist/core/format/backend-ast/printer.test.d.ts.map +1 -0
  36. package/dist/core/format/backend-ast/printer.test.js +796 -0
  37. package/dist/core/format/backend-ast/printer.test.js.map +1 -0
  38. package/dist/core/format/backend-ast/types.d.ts +66 -14
  39. package/dist/core/format/backend-ast/types.d.ts.map +1 -1
  40. package/dist/core/format/backend-ast/utils.d.ts +12 -8
  41. package/dist/core/format/backend-ast/utils.d.ts.map +1 -1
  42. package/dist/core/format/backend-ast/utils.js +222 -19
  43. package/dist/core/format/backend-ast/utils.js.map +1 -1
  44. package/dist/core/format/backend-ast/utils.test.d.ts +2 -0
  45. package/dist/core/format/backend-ast/utils.test.d.ts.map +1 -0
  46. package/dist/core/format/backend-ast/utils.test.js +142 -0
  47. package/dist/core/format/backend-ast/utils.test.js.map +1 -0
  48. package/dist/core/format/module-emitter/assembly.d.ts +2 -2
  49. package/dist/core/format/module-emitter/assembly.d.ts.map +1 -1
  50. package/dist/core/format/module-emitter/assembly.js +7 -3
  51. package/dist/core/format/module-emitter/assembly.js.map +1 -1
  52. package/dist/core/format/module-emitter/header.d.ts +2 -1
  53. package/dist/core/format/module-emitter/header.d.ts.map +1 -1
  54. package/dist/core/format/module-emitter/header.js +2 -2
  55. package/dist/core/format/module-emitter/header.js.map +1 -1
  56. package/dist/core/format/module-emitter/orchestrator.js +1 -1
  57. package/dist/core/format/module-emitter/orchestrator.js.map +1 -1
  58. package/dist/core/format/module-emitter/static-container.d.ts.map +1 -1
  59. package/dist/core/format/module-emitter/static-container.js +3 -5
  60. package/dist/core/format/module-emitter/static-container.js.map +1 -1
  61. package/dist/core/module-emitter.test.js +1 -0
  62. package/dist/core/module-emitter.test.js.map +1 -1
  63. package/dist/core/semantic/boolean-context.d.ts.map +1 -1
  64. package/dist/core/semantic/boolean-context.js +45 -49
  65. package/dist/core/semantic/boolean-context.js.map +1 -1
  66. package/dist/core/semantic/imports.d.ts.map +1 -1
  67. package/dist/core/semantic/imports.js +25 -15
  68. package/dist/core/semantic/imports.js.map +1 -1
  69. package/dist/core/semantic/imports.test.js +43 -0
  70. package/dist/core/semantic/imports.test.js.map +1 -1
  71. package/dist/core/semantic/type-resolution.d.ts +1 -0
  72. package/dist/core/semantic/type-resolution.d.ts.map +1 -1
  73. package/dist/core/semantic/type-resolution.js +166 -5
  74. package/dist/core/semantic/type-resolution.js.map +1 -1
  75. package/dist/core/semantic/type-resolution.test.js +35 -0
  76. package/dist/core/semantic/type-resolution.test.js.map +1 -1
  77. package/dist/emitter-types/core.d.ts +24 -10
  78. package/dist/emitter-types/core.d.ts.map +1 -1
  79. package/dist/emitter.d.ts.map +1 -1
  80. package/dist/emitter.js +124 -44
  81. package/dist/emitter.js.map +1 -1
  82. package/dist/expression-emitter.d.ts.map +1 -1
  83. package/dist/expression-emitter.js +797 -17
  84. package/dist/expression-emitter.js.map +1 -1
  85. package/dist/expressions/access.d.ts.map +1 -1
  86. package/dist/expressions/access.js +65 -25
  87. package/dist/expressions/access.js.map +1 -1
  88. package/dist/expressions/calls/call-analysis.d.ts +0 -10
  89. package/dist/expressions/calls/call-analysis.d.ts.map +1 -1
  90. package/dist/expressions/calls/call-analysis.js +3 -62
  91. package/dist/expressions/calls/call-analysis.js.map +1 -1
  92. package/dist/expressions/calls/call-emitter.d.ts.map +1 -1
  93. package/dist/expressions/calls/call-emitter.js +97 -196
  94. package/dist/expressions/calls/call-emitter.js.map +1 -1
  95. package/dist/expressions/calls/new-emitter.d.ts.map +1 -1
  96. package/dist/expressions/calls/new-emitter.js +36 -69
  97. package/dist/expressions/calls/new-emitter.js.map +1 -1
  98. package/dist/expressions/collections.d.ts +3 -0
  99. package/dist/expressions/collections.d.ts.map +1 -1
  100. package/dist/expressions/collections.js +238 -57
  101. package/dist/expressions/collections.js.map +1 -1
  102. package/dist/expressions/functions.d.ts.map +1 -1
  103. package/dist/expressions/functions.js +1 -7
  104. package/dist/expressions/functions.js.map +1 -1
  105. package/dist/expressions/identifiers.d.ts.map +1 -1
  106. package/dist/expressions/identifiers.js +24 -38
  107. package/dist/expressions/identifiers.js.map +1 -1
  108. package/dist/expressions/index.test.js +245 -0
  109. package/dist/expressions/index.test.js.map +1 -1
  110. package/dist/expressions/literals.d.ts.map +1 -1
  111. package/dist/expressions/literals.js +9 -41
  112. package/dist/expressions/literals.js.map +1 -1
  113. package/dist/expressions/operators/assignment-emitter.d.ts.map +1 -1
  114. package/dist/expressions/operators/assignment-emitter.js +2 -6
  115. package/dist/expressions/operators/assignment-emitter.js.map +1 -1
  116. package/dist/expressions/operators/binary-emitter.d.ts.map +1 -1
  117. package/dist/expressions/operators/binary-emitter.js +102 -77
  118. package/dist/expressions/operators/binary-emitter.js.map +1 -1
  119. package/dist/expressions/operators/logical-emitter.d.ts.map +1 -1
  120. package/dist/expressions/operators/logical-emitter.js +1 -3
  121. package/dist/expressions/operators/logical-emitter.js.map +1 -1
  122. package/dist/expressions/operators/unary-emitter.d.ts.map +1 -1
  123. package/dist/expressions/operators/unary-emitter.js +9 -20
  124. package/dist/expressions/operators/unary-emitter.js.map +1 -1
  125. package/dist/expressions/other.d.ts.map +1 -1
  126. package/dist/expressions/other.js +57 -4
  127. package/dist/expressions/other.js.map +1 -1
  128. package/dist/generator-exchange.d.ts.map +1 -1
  129. package/dist/generator-exchange.js +3 -2
  130. package/dist/generator-exchange.js.map +1 -1
  131. package/dist/generator-wrapper.d.ts.map +1 -1
  132. package/dist/generator-wrapper.js +27 -56
  133. package/dist/generator-wrapper.js.map +1 -1
  134. package/dist/integration.test.js +393 -5
  135. package/dist/integration.test.js.map +1 -1
  136. package/dist/json-aot-generic.test.js +3 -0
  137. package/dist/json-aot-generic.test.js.map +1 -1
  138. package/dist/patterns.d.ts.map +1 -1
  139. package/dist/patterns.js +19 -40
  140. package/dist/patterns.js.map +1 -1
  141. package/dist/specialization/type-aliases.test.js +8 -0
  142. package/dist/specialization/type-aliases.test.js.map +1 -1
  143. package/dist/statements/classes/members/methods.d.ts.map +1 -1
  144. package/dist/statements/classes/members/methods.js +5 -22
  145. package/dist/statements/classes/members/methods.js.map +1 -1
  146. package/dist/statements/classes/parameters.d.ts.map +1 -1
  147. package/dist/statements/classes/parameters.js +2 -1
  148. package/dist/statements/classes/parameters.js.map +1 -1
  149. package/dist/statements/classes/properties.d.ts.map +1 -1
  150. package/dist/statements/classes/properties.js +5 -16
  151. package/dist/statements/classes/properties.js.map +1 -1
  152. package/dist/statements/control/conditionals/guard-analysis.d.ts +44 -1
  153. package/dist/statements/control/conditionals/guard-analysis.d.ts.map +1 -1
  154. package/dist/statements/control/conditionals/guard-analysis.js +301 -125
  155. package/dist/statements/control/conditionals/guard-analysis.js.map +1 -1
  156. package/dist/statements/control/conditionals/if-emitter.d.ts.map +1 -1
  157. package/dist/statements/control/conditionals/if-emitter.js +182 -53
  158. package/dist/statements/control/conditionals/if-emitter.js.map +1 -1
  159. package/dist/statements/control/exceptions.d.ts.map +1 -1
  160. package/dist/statements/control/exceptions.js +2 -4
  161. package/dist/statements/control/exceptions.js.map +1 -1
  162. package/dist/statements/control/loops.d.ts.map +1 -1
  163. package/dist/statements/control/loops.js +3 -5
  164. package/dist/statements/control/loops.js.map +1 -1
  165. package/dist/statements/declarations/classes.d.ts.map +1 -1
  166. package/dist/statements/declarations/classes.js +2 -4
  167. package/dist/statements/declarations/classes.js.map +1 -1
  168. package/dist/statements/declarations/functions.d.ts.map +1 -1
  169. package/dist/statements/declarations/functions.js +38 -79
  170. package/dist/statements/declarations/functions.js.map +1 -1
  171. package/dist/statements/declarations/interfaces-mutable-storage.test.js +10 -2
  172. package/dist/statements/declarations/interfaces-mutable-storage.test.js.map +1 -1
  173. package/dist/statements/declarations/interfaces.d.ts.map +1 -1
  174. package/dist/statements/declarations/interfaces.js +4 -12
  175. package/dist/statements/declarations/interfaces.js.map +1 -1
  176. package/dist/statements/declarations/type-aliases.d.ts.map +1 -1
  177. package/dist/statements/declarations/type-aliases.js +5 -9
  178. package/dist/statements/declarations/type-aliases.js.map +1 -1
  179. package/dist/statements/declarations/variables.d.ts.map +1 -1
  180. package/dist/statements/declarations/variables.js +55 -51
  181. package/dist/statements/declarations/variables.js.map +1 -1
  182. package/dist/statements/index.test.js +1026 -0
  183. package/dist/statements/index.test.js.map +1 -1
  184. package/dist/types/dictionaries.d.ts.map +1 -1
  185. package/dist/types/dictionaries.js +5 -5
  186. package/dist/types/dictionaries.js.map +1 -1
  187. package/dist/types/functions.d.ts.map +1 -1
  188. package/dist/types/functions.js +5 -25
  189. package/dist/types/functions.js.map +1 -1
  190. package/dist/types/primitives.d.ts.map +1 -1
  191. package/dist/types/primitives.js.map +1 -1
  192. package/dist/types/references.d.ts.map +1 -1
  193. package/dist/types/references.js +65 -128
  194. package/dist/types/references.js.map +1 -1
  195. package/dist/types/references.test.js +170 -46
  196. package/dist/types/references.test.js.map +1 -1
  197. package/dist/types/tuples.d.ts.map +1 -1
  198. package/dist/types/tuples.js +7 -17
  199. package/dist/types/tuples.js.map +1 -1
  200. package/dist/types/unions.d.ts.map +1 -1
  201. package/dist/types/unions.js +2 -5
  202. package/dist/types/unions.js.map +1 -1
  203. package/package.json +2 -2
  204. package/dist/expressions/parentheses.d.ts +0 -4
  205. package/dist/expressions/parentheses.d.ts.map +0 -1
  206. package/dist/expressions/parentheses.js +0 -91
  207. package/dist/expressions/parentheses.js.map +0 -1
@@ -5,8 +5,11 @@
5
5
  * Primary entry point is emitExpressionAst which returns [CSharpExpressionAst, EmitterContext].
6
6
  */
7
7
  import { emitTypeAst } from "./type-emitter.js";
8
- import { substituteTypeArgs, resolveTypeAlias, stripNullish, } from "./core/semantic/type-resolution.js";
9
- import { renderTypeAst } from "./core/format/backend-ast/utils.js";
8
+ import { substituteTypeArgs, resolveTypeAlias, stripNullish, getPropertyType, getAllPropertySignatures, resolveLocalTypeInfo, } from "./core/semantic/type-resolution.js";
9
+ import { identifierExpression, identifierType, nullLiteral, stringLiteral, } from "./core/format/backend-ast/builders.js";
10
+ import { getIdentifierTypeName } from "./core/format/backend-ast/utils.js";
11
+ import { allocateLocalName } from "./core/format/local-names.js";
12
+ import { emitCSharpName } from "./naming-policy.js";
10
13
  // Import expression emitters from specialized modules
11
14
  import { emitLiteral } from "./expressions/literals.js";
12
15
  import { emitIdentifier } from "./expressions/identifiers.js";
@@ -17,6 +20,786 @@ import { emitNew } from "./expressions/calls/new-emitter.js";
17
20
  import { emitBinary, emitLogical, emitUnary, emitUpdate, emitAssignment, emitConditional, } from "./expressions/operators.js";
18
21
  import { emitFunctionExpression, emitArrowFunction, } from "./expressions/functions.js";
19
22
  import { emitTemplateLiteral, emitSpread, emitAwait, } from "./expressions/other.js";
23
+ const hasNullishBranch = (type) => {
24
+ if (!type || type.kind !== "unionType")
25
+ return false;
26
+ return type.types.some((member) => member.kind === "primitiveType" &&
27
+ (member.name === "null" || member.name === "undefined"));
28
+ };
29
+ const buildDelegateType = (parameterTypes, returnType) => identifierType("global::System.Func", [...parameterTypes, returnType]);
30
+ const collectLocalStructuralProperties = (info) => {
31
+ switch (info.kind) {
32
+ case "interface": {
33
+ if (info.members.some((member) => member.kind === "methodSignature")) {
34
+ return undefined;
35
+ }
36
+ const props = [];
37
+ for (const member of info.members) {
38
+ if (member.kind !== "propertySignature")
39
+ continue;
40
+ props.push({
41
+ name: member.name,
42
+ type: member.type,
43
+ isOptional: member.isOptional,
44
+ });
45
+ }
46
+ return props;
47
+ }
48
+ case "class": {
49
+ if (info.members.some((member) => member.kind === "methodDeclaration")) {
50
+ return undefined;
51
+ }
52
+ const props = [];
53
+ for (const member of info.members) {
54
+ if (member.kind !== "propertyDeclaration")
55
+ continue;
56
+ if (!member.type)
57
+ return undefined;
58
+ props.push({
59
+ name: member.name,
60
+ type: member.type,
61
+ isOptional: false,
62
+ });
63
+ }
64
+ return props;
65
+ }
66
+ case "typeAlias": {
67
+ const aliasType = info.type;
68
+ if (aliasType.kind !== "objectType")
69
+ return undefined;
70
+ if (aliasType.members.some((member) => member.kind === "methodSignature")) {
71
+ return undefined;
72
+ }
73
+ return aliasType.members
74
+ .filter((member) => member.kind === "propertySignature")
75
+ .map((member) => ({
76
+ name: member.name,
77
+ type: member.type,
78
+ isOptional: member.isOptional,
79
+ }));
80
+ }
81
+ default:
82
+ return undefined;
83
+ }
84
+ };
85
+ const parseEmitterClrTypeString = (clrType) => {
86
+ if (clrType === "System.Void" || clrType === "void") {
87
+ return { kind: "voidType" };
88
+ }
89
+ const primitiveMap = {
90
+ "System.String": { kind: "primitiveType", name: "string" },
91
+ string: { kind: "primitiveType", name: "string" },
92
+ "System.Int32": { kind: "primitiveType", name: "int" },
93
+ int: { kind: "primitiveType", name: "int" },
94
+ "System.Double": { kind: "primitiveType", name: "number" },
95
+ double: { kind: "primitiveType", name: "number" },
96
+ "System.Boolean": { kind: "primitiveType", name: "boolean" },
97
+ bool: { kind: "primitiveType", name: "boolean" },
98
+ "System.Char": { kind: "primitiveType", name: "char" },
99
+ char: { kind: "primitiveType", name: "char" },
100
+ "System.Int64": { kind: "referenceType", name: "long" },
101
+ long: { kind: "referenceType", name: "long" },
102
+ "System.Object": { kind: "referenceType", name: "object" },
103
+ object: { kind: "referenceType", name: "object" },
104
+ };
105
+ const primitive = primitiveMap[clrType];
106
+ if (primitive)
107
+ return primitive;
108
+ if (clrType.endsWith("[]")) {
109
+ return {
110
+ kind: "arrayType",
111
+ elementType: parseEmitterClrTypeString(clrType.slice(0, -2)),
112
+ };
113
+ }
114
+ if (clrType.endsWith("*")) {
115
+ return parseEmitterClrTypeString(clrType.slice(0, -1));
116
+ }
117
+ if (clrType.startsWith("System.Nullable`1")) {
118
+ const innerMatch = clrType.match(/System\.Nullable`1\[\[([^\]]+)\]\]/);
119
+ if (innerMatch?.[1]) {
120
+ return {
121
+ kind: "unionType",
122
+ types: [
123
+ parseEmitterClrTypeString(innerMatch[1]),
124
+ { kind: "primitiveType", name: "undefined" },
125
+ ],
126
+ };
127
+ }
128
+ }
129
+ if (/^T\d*$/.test(clrType) || /^T[A-Z][a-zA-Z]*$/.test(clrType)) {
130
+ return { kind: "typeParameterType", name: clrType };
131
+ }
132
+ const underscoreInstantiationMatch = clrType.match(/^(.+?)_(\d+)\[\[(.+)\]\]$/);
133
+ if (underscoreInstantiationMatch?.[1] &&
134
+ underscoreInstantiationMatch[2] &&
135
+ underscoreInstantiationMatch[3]) {
136
+ const baseName = underscoreInstantiationMatch[1];
137
+ const arity = Number.parseInt(underscoreInstantiationMatch[2], 10);
138
+ const args = splitEmitterTypeArguments(underscoreInstantiationMatch[3]);
139
+ return {
140
+ kind: "referenceType",
141
+ name: `${baseName}_${arity}`,
142
+ typeArguments: args.length === arity
143
+ ? args.map((arg) => parseEmitterClrTypeString(arg.trim()))
144
+ : undefined,
145
+ resolvedClrType: clrType,
146
+ };
147
+ }
148
+ const genericMatch = clrType.match(/^(.+)`(\d+)(?:\[\[(.+)\]\])?$/);
149
+ if (genericMatch?.[1] && genericMatch[2]) {
150
+ const baseName = genericMatch[1];
151
+ const arity = Number.parseInt(genericMatch[2], 10);
152
+ const typeArguments = genericMatch[3]
153
+ ? splitEmitterTypeArguments(genericMatch[3]).map((arg) => parseEmitterClrTypeString(arg.trim()))
154
+ : Array.from({ length: arity }, (_, index) => ({
155
+ kind: "typeParameterType",
156
+ name: index === 0 ? "T" : `T${index + 1}`,
157
+ }));
158
+ return {
159
+ kind: "referenceType",
160
+ name: baseName,
161
+ typeArguments,
162
+ resolvedClrType: clrType,
163
+ };
164
+ }
165
+ return {
166
+ kind: "referenceType",
167
+ name: clrType,
168
+ resolvedClrType: clrType,
169
+ };
170
+ };
171
+ const splitEmitterTypeArguments = (text) => {
172
+ const parts = [];
173
+ let depth = 0;
174
+ let current = "";
175
+ for (const char of text) {
176
+ if (char === "[") {
177
+ depth++;
178
+ current += char;
179
+ continue;
180
+ }
181
+ if (char === "]") {
182
+ depth--;
183
+ current += char;
184
+ continue;
185
+ }
186
+ if (char === "," && depth === 0) {
187
+ parts.push(current.trim());
188
+ current = "";
189
+ continue;
190
+ }
191
+ current += char;
192
+ }
193
+ if (current.trim()) {
194
+ parts.push(current.trim());
195
+ }
196
+ return parts;
197
+ };
198
+ const addUndefinedToBindingType = (type) => {
199
+ if (type.kind === "unionType" &&
200
+ type.types.some((candidate) => candidate.kind === "primitiveType" && candidate.name === "undefined")) {
201
+ return type;
202
+ }
203
+ return {
204
+ kind: "unionType",
205
+ types: [type, { kind: "primitiveType", name: "undefined" }],
206
+ };
207
+ };
208
+ const parseBindingPropertyType = (normalizedSignature) => {
209
+ if (!normalizedSignature) {
210
+ return { kind: "unknownType" };
211
+ }
212
+ const indexerMatch = normalizedSignature.match(/\|\[[^\]]*\]:([^|]+)\|/);
213
+ if (indexerMatch?.[1]) {
214
+ return parseEmitterClrTypeString(indexerMatch[1]);
215
+ }
216
+ const propertyMatch = normalizedSignature.match(/\|:([^|]+)\|/);
217
+ if (propertyMatch?.[1]) {
218
+ return parseEmitterClrTypeString(propertyMatch[1]);
219
+ }
220
+ const fieldParts = normalizedSignature.split("|");
221
+ if (fieldParts.length >= 2 && fieldParts[1]) {
222
+ return parseEmitterClrTypeString(fieldParts[1]);
223
+ }
224
+ return { kind: "unknownType" };
225
+ };
226
+ const collectBindingStructuralProperties = (type, context) => {
227
+ const registry = context.bindingsRegistry;
228
+ if (!registry || registry.size === 0) {
229
+ return undefined;
230
+ }
231
+ const candidates = new Set();
232
+ const add = (value) => {
233
+ if (value && value.length > 0) {
234
+ candidates.add(value);
235
+ if (value.includes(".")) {
236
+ candidates.add(value.split(".").pop() ?? value);
237
+ }
238
+ }
239
+ };
240
+ add(type.name);
241
+ add(type.resolvedClrType);
242
+ add(type.typeId?.tsName);
243
+ add(type.typeId?.clrName);
244
+ for (const candidate of candidates) {
245
+ const binding = registry.get(candidate);
246
+ if (!binding)
247
+ continue;
248
+ if (binding.members.some((member) => member.kind === "method")) {
249
+ return undefined;
250
+ }
251
+ const props = binding.members
252
+ .filter((member) => member.kind === "property")
253
+ .map((member) => ({
254
+ name: member.alias,
255
+ type: member.semanticType !== undefined
256
+ ? member.semanticOptional === true
257
+ ? addUndefinedToBindingType(member.semanticType)
258
+ : member.semanticType
259
+ : parseBindingPropertyType(member.signature),
260
+ isOptional: member.semanticOptional === true,
261
+ }));
262
+ if (props.length > 0) {
263
+ return props;
264
+ }
265
+ }
266
+ return undefined;
267
+ };
268
+ const collectStructuralProperties = (type, context) => {
269
+ if (!type)
270
+ return undefined;
271
+ const resolved = resolveTypeAlias(stripNullish(type), context);
272
+ if (resolved.kind === "objectType") {
273
+ if (resolved.members.some((member) => member.kind === "methodSignature")) {
274
+ return undefined;
275
+ }
276
+ return resolved.members
277
+ .filter((member) => member.kind === "propertySignature")
278
+ .map((member) => ({
279
+ name: member.name,
280
+ type: member.type,
281
+ isOptional: member.isOptional,
282
+ }));
283
+ }
284
+ if (resolved.kind !== "referenceType") {
285
+ return undefined;
286
+ }
287
+ const inheritedInterfaceProps = getAllPropertySignatures(resolved, context);
288
+ if (inheritedInterfaceProps && inheritedInterfaceProps.length > 0) {
289
+ return inheritedInterfaceProps.map((member) => ({
290
+ name: member.name,
291
+ type: member.type,
292
+ isOptional: member.isOptional,
293
+ }));
294
+ }
295
+ const localInfo = resolveLocalTypeInfo(resolved, context)?.info;
296
+ if (localInfo) {
297
+ return collectLocalStructuralProperties(localInfo);
298
+ }
299
+ if (resolved.structuralMembers && resolved.structuralMembers.length > 0) {
300
+ if (resolved.structuralMembers.some((member) => member.kind === "methodSignature")) {
301
+ return undefined;
302
+ }
303
+ return resolved.structuralMembers
304
+ .filter((member) => member.kind === "propertySignature")
305
+ .map((member) => ({
306
+ name: member.name,
307
+ type: member.type,
308
+ isOptional: member.isOptional,
309
+ }));
310
+ }
311
+ return collectBindingStructuralProperties(resolved, context);
312
+ };
313
+ const resolveAnonymousStructuralReferenceType = (type, context) => {
314
+ const resolved = resolveTypeAlias(stripNullish(type), context);
315
+ if (resolved.kind !== "objectType")
316
+ return undefined;
317
+ const propertyNames = resolved.members
318
+ .filter((member) => member.kind === "propertySignature")
319
+ .map((member) => member.name)
320
+ .sort();
321
+ if (propertyNames.length === 0)
322
+ return undefined;
323
+ const candidateMaps = [];
324
+ if (context.localTypes) {
325
+ candidateMaps.push(context.localTypes);
326
+ }
327
+ if (context.options.moduleMap) {
328
+ for (const module of context.options.moduleMap.values()) {
329
+ if (module.localTypes) {
330
+ candidateMaps.push(module.localTypes);
331
+ }
332
+ }
333
+ }
334
+ const matches = new Set();
335
+ for (const localTypes of candidateMaps) {
336
+ for (const [typeName, info] of localTypes.entries()) {
337
+ if (info.kind !== "class" || !typeName.startsWith("__Anon_"))
338
+ continue;
339
+ const candidateProps = info.members
340
+ .filter((member) => member.kind === "propertyDeclaration")
341
+ .map((member) => member.name)
342
+ .sort();
343
+ if (candidateProps.length === propertyNames.length &&
344
+ candidateProps.every((name, index) => name === propertyNames[index])) {
345
+ matches.add(typeName);
346
+ }
347
+ }
348
+ }
349
+ if (matches.size !== 1)
350
+ return undefined;
351
+ const onlyMatch = [...matches][0];
352
+ return onlyMatch
353
+ ? { kind: "referenceType", name: onlyMatch }
354
+ : undefined;
355
+ };
356
+ const isSameNominalType = (sourceType, targetType, context) => {
357
+ if (!sourceType || !targetType)
358
+ return false;
359
+ const sourceBase = stripNullish(sourceType);
360
+ const targetBase = stripNullish(targetType);
361
+ if (sourceBase.kind === "referenceType" &&
362
+ targetBase.kind === "referenceType") {
363
+ if (sourceBase.name === targetBase.name) {
364
+ return true;
365
+ }
366
+ if (sourceBase.typeId?.stableId !== undefined &&
367
+ sourceBase.typeId.stableId === targetBase.typeId?.stableId) {
368
+ return true;
369
+ }
370
+ if (sourceBase.resolvedClrType !== undefined &&
371
+ sourceBase.resolvedClrType === targetBase.resolvedClrType) {
372
+ return true;
373
+ }
374
+ }
375
+ const sourceResolved = resolveTypeAlias(sourceBase, context);
376
+ const targetResolved = resolveTypeAlias(targetBase, context);
377
+ if (sourceResolved.kind !== "referenceType" ||
378
+ targetResolved.kind !== "referenceType") {
379
+ return false;
380
+ }
381
+ return (sourceResolved.name === targetResolved.name ||
382
+ (sourceResolved.resolvedClrType !== undefined &&
383
+ sourceResolved.resolvedClrType === targetResolved.resolvedClrType));
384
+ };
385
+ const buildStructuralSourceAccess = (sourceExpression, sourceType, propertyName, context) => {
386
+ const resolvedSource = resolveTypeAlias(stripNullish(sourceType), context);
387
+ if (resolvedSource.kind === "dictionaryType") {
388
+ return {
389
+ kind: "elementAccessExpression",
390
+ expression: sourceExpression,
391
+ arguments: [stringLiteral(propertyName)],
392
+ };
393
+ }
394
+ return {
395
+ kind: "memberAccessExpression",
396
+ expression: sourceExpression,
397
+ memberName: emitCSharpName(propertyName, "properties", context),
398
+ };
399
+ };
400
+ const isDirectlyReusableExpression = (expression) => expression.kind === "identifierExpression" ||
401
+ expression.kind === "memberAccessExpression" ||
402
+ expression.kind === "elementAccessExpression";
403
+ const getArrayElementType = (type, context) => {
404
+ if (!type)
405
+ return undefined;
406
+ const resolved = resolveTypeAlias(stripNullish(type), context);
407
+ if (resolved.kind === "arrayType")
408
+ return resolved.elementType;
409
+ if (resolved.kind === "tupleType") {
410
+ if (resolved.elementTypes.length === 1)
411
+ return resolved.elementTypes[0];
412
+ return undefined;
413
+ }
414
+ if (resolved.kind === "referenceType" &&
415
+ (resolved.name === "Array" ||
416
+ resolved.name === "ReadonlyArray" ||
417
+ resolved.name === "JSArray") &&
418
+ resolved.typeArguments?.length === 1) {
419
+ return resolved.typeArguments[0];
420
+ }
421
+ return undefined;
422
+ };
423
+ const getDictionaryValueType = (type, context) => {
424
+ if (!type)
425
+ return undefined;
426
+ const resolved = resolveTypeAlias(stripNullish(type), context);
427
+ if (resolved.kind !== "dictionaryType")
428
+ return undefined;
429
+ return resolved.valueType;
430
+ };
431
+ const tryAdaptStructuralExpressionAst = (emittedAst, sourceType, context, expectedType) => {
432
+ if (!expectedType || !sourceType)
433
+ return undefined;
434
+ if (isSameNominalType(sourceType, expectedType, context)) {
435
+ return undefined;
436
+ }
437
+ const strippedExpectedType = stripNullish(expectedType);
438
+ const anonymousStructuralTarget = resolveAnonymousStructuralReferenceType(expectedType, context);
439
+ const targetStructuralType = anonymousStructuralTarget ??
440
+ resolveTypeAlias(strippedExpectedType, context);
441
+ const targetEmissionType = anonymousStructuralTarget ??
442
+ (strippedExpectedType.kind === "referenceType"
443
+ ? strippedExpectedType
444
+ : undefined);
445
+ const targetProps = collectStructuralProperties(targetStructuralType, context);
446
+ if (targetProps && targetProps.length > 0) {
447
+ if (!targetEmissionType && targetStructuralType.kind === "objectType") {
448
+ return undefined;
449
+ }
450
+ const sourceProps = collectStructuralProperties(sourceType, context);
451
+ if (!sourceProps || sourceProps.length === 0)
452
+ return undefined;
453
+ const sourcePropNames = new Set(sourceProps.map((prop) => prop.name));
454
+ const materializedProps = targetProps.filter((prop) => prop.isOptional || sourcePropNames.has(prop.name));
455
+ if (materializedProps.length === 0)
456
+ return undefined;
457
+ for (const prop of targetProps) {
458
+ if (!prop.isOptional && !sourcePropNames.has(prop.name)) {
459
+ return undefined;
460
+ }
461
+ if (!sourcePropNames.has(prop.name))
462
+ continue;
463
+ if (!getPropertyType(sourceType, prop.name, context)) {
464
+ return undefined;
465
+ }
466
+ }
467
+ let currentContext = context;
468
+ const [targetTypeAst, withType] = emitTypeAst(targetEmissionType ?? targetStructuralType, currentContext);
469
+ currentContext = withType;
470
+ const safeTargetTypeAst = targetTypeAst.kind === "nullableType"
471
+ ? targetTypeAst.underlyingType
472
+ : targetTypeAst;
473
+ const sourcePropMap = new Map(sourceProps.map((prop) => [prop.name, prop]));
474
+ const buildInitializer = (sourceExpression, initContext) => {
475
+ let currentInitContext = initContext;
476
+ const assignments = materializedProps
477
+ .filter((prop) => sourcePropNames.has(prop.name))
478
+ .map((prop) => {
479
+ const sourceProp = sourcePropMap.get(prop.name);
480
+ const sourceAccess = buildStructuralSourceAccess(sourceExpression, sourceType, prop.name, currentInitContext);
481
+ const [adaptedValueAst, adaptedValueContext] = tryAdaptStructuralExpressionAst(sourceAccess, sourceProp?.type, currentInitContext, prop.type) ?? [sourceAccess, currentInitContext];
482
+ currentInitContext = adaptedValueContext;
483
+ return {
484
+ kind: "assignmentExpression",
485
+ operatorToken: "=",
486
+ left: {
487
+ kind: "identifierExpression",
488
+ identifier: emitCSharpName(prop.name, "properties", currentInitContext),
489
+ },
490
+ right: adaptedValueAst,
491
+ };
492
+ });
493
+ return [
494
+ {
495
+ kind: "objectCreationExpression",
496
+ type: safeTargetTypeAst,
497
+ arguments: [],
498
+ initializer: assignments,
499
+ },
500
+ currentInitContext,
501
+ ];
502
+ };
503
+ const sourceMayBeNullish = hasNullishBranch(sourceType);
504
+ if (emittedAst.kind === "identifierExpression") {
505
+ const [initializer, initializerContext] = buildInitializer(emittedAst, currentContext);
506
+ if (!sourceMayBeNullish) {
507
+ return [initializer, initializerContext];
508
+ }
509
+ return [
510
+ {
511
+ kind: "conditionalExpression",
512
+ condition: {
513
+ kind: "binaryExpression",
514
+ operatorToken: "==",
515
+ left: emittedAst,
516
+ right: nullLiteral(),
517
+ },
518
+ whenTrue: {
519
+ kind: "defaultExpression",
520
+ type: safeTargetTypeAst,
521
+ },
522
+ whenFalse: initializer,
523
+ },
524
+ initializerContext,
525
+ ];
526
+ }
527
+ const temp = allocateLocalName("__struct", currentContext);
528
+ currentContext = temp.context;
529
+ const tempIdentifier = {
530
+ kind: "identifierExpression",
531
+ identifier: temp.emittedName,
532
+ };
533
+ const statements = [
534
+ {
535
+ kind: "localDeclarationStatement",
536
+ modifiers: [],
537
+ type: { kind: "varType" },
538
+ declarators: [{ name: temp.emittedName, initializer: emittedAst }],
539
+ },
540
+ ];
541
+ if (sourceMayBeNullish) {
542
+ statements.push({
543
+ kind: "ifStatement",
544
+ condition: {
545
+ kind: "binaryExpression",
546
+ operatorToken: "==",
547
+ left: tempIdentifier,
548
+ right: nullLiteral(),
549
+ },
550
+ thenStatement: {
551
+ kind: "blockStatement",
552
+ statements: [
553
+ {
554
+ kind: "returnStatement",
555
+ expression: {
556
+ kind: "defaultExpression",
557
+ type: safeTargetTypeAst,
558
+ },
559
+ },
560
+ ],
561
+ },
562
+ });
563
+ }
564
+ const [initializer, initializerContext] = buildInitializer(tempIdentifier, currentContext);
565
+ currentContext = initializerContext;
566
+ statements.push({
567
+ kind: "returnStatement",
568
+ expression: initializer,
569
+ });
570
+ const lambdaAst = {
571
+ kind: "lambdaExpression",
572
+ isAsync: false,
573
+ parameters: [],
574
+ body: {
575
+ kind: "blockStatement",
576
+ statements,
577
+ },
578
+ };
579
+ return [
580
+ {
581
+ kind: "invocationExpression",
582
+ expression: {
583
+ kind: "parenthesizedExpression",
584
+ expression: {
585
+ kind: "castExpression",
586
+ type: buildDelegateType([], safeTargetTypeAst),
587
+ expression: {
588
+ kind: "parenthesizedExpression",
589
+ expression: lambdaAst,
590
+ },
591
+ },
592
+ },
593
+ arguments: [],
594
+ },
595
+ currentContext,
596
+ ];
597
+ }
598
+ const targetElementType = getArrayElementType(expectedType, context);
599
+ const sourceElementType = getArrayElementType(sourceType, context);
600
+ if (targetElementType && sourceElementType) {
601
+ const item = allocateLocalName("__item", context);
602
+ let currentContext = item.context;
603
+ const itemIdentifier = {
604
+ kind: "identifierExpression",
605
+ identifier: item.emittedName,
606
+ };
607
+ const [adaptedElementAst, adaptedContext] = tryAdaptStructuralExpressionAst(itemIdentifier, sourceElementType, currentContext, targetElementType) ?? [undefined, currentContext];
608
+ currentContext = adaptedContext;
609
+ if (adaptedElementAst !== undefined) {
610
+ const selectAst = {
611
+ kind: "invocationExpression",
612
+ expression: {
613
+ ...identifierExpression("global::System.Linq.Enumerable.Select"),
614
+ },
615
+ arguments: [
616
+ emittedAst,
617
+ {
618
+ kind: "lambdaExpression",
619
+ isAsync: false,
620
+ parameters: [{ name: item.emittedName }],
621
+ body: adaptedElementAst,
622
+ },
623
+ ],
624
+ };
625
+ const toArrayAst = {
626
+ kind: "invocationExpression",
627
+ expression: {
628
+ ...identifierExpression("global::System.Linq.Enumerable.ToArray"),
629
+ },
630
+ arguments: [selectAst],
631
+ };
632
+ if (!hasNullishBranch(sourceType)) {
633
+ return [toArrayAst, currentContext];
634
+ }
635
+ if (isDirectlyReusableExpression(emittedAst)) {
636
+ return [
637
+ {
638
+ kind: "conditionalExpression",
639
+ condition: {
640
+ kind: "binaryExpression",
641
+ operatorToken: "==",
642
+ left: emittedAst,
643
+ right: nullLiteral(),
644
+ },
645
+ whenTrue: { kind: "defaultExpression" },
646
+ whenFalse: toArrayAst,
647
+ },
648
+ currentContext,
649
+ ];
650
+ }
651
+ }
652
+ }
653
+ const targetValueType = getDictionaryValueType(expectedType, context);
654
+ const sourceValueType = getDictionaryValueType(sourceType, context);
655
+ if (targetValueType && sourceValueType) {
656
+ let currentContext = context;
657
+ const [targetValueTypeAst, valueTypeContext] = emitTypeAst(targetValueType, currentContext);
658
+ currentContext = valueTypeContext;
659
+ const dictTypeAst = identifierType("global::System.Collections.Generic.Dictionary", [{ kind: "predefinedType", keyword: "string" }, targetValueTypeAst]);
660
+ const sourceTemp = allocateLocalName("__dict", currentContext);
661
+ currentContext = sourceTemp.context;
662
+ const entryTemp = allocateLocalName("__entry", currentContext);
663
+ currentContext = entryTemp.context;
664
+ const resultTemp = allocateLocalName("__result", currentContext);
665
+ currentContext = resultTemp.context;
666
+ const entryValueAst = {
667
+ kind: "memberAccessExpression",
668
+ expression: {
669
+ kind: "identifierExpression",
670
+ identifier: entryTemp.emittedName,
671
+ },
672
+ memberName: "Value",
673
+ };
674
+ const [adaptedValueAst, adaptedContext] = tryAdaptStructuralExpressionAst(entryValueAst, sourceValueType, currentContext, targetValueType) ?? [undefined, currentContext];
675
+ currentContext = adaptedContext;
676
+ if (adaptedValueAst !== undefined) {
677
+ const statements = [
678
+ {
679
+ kind: "localDeclarationStatement",
680
+ modifiers: [],
681
+ type: { kind: "varType" },
682
+ declarators: [
683
+ {
684
+ name: sourceTemp.emittedName,
685
+ initializer: emittedAst,
686
+ },
687
+ ],
688
+ },
689
+ {
690
+ kind: "ifStatement",
691
+ condition: {
692
+ kind: "binaryExpression",
693
+ operatorToken: "==",
694
+ left: {
695
+ kind: "identifierExpression",
696
+ identifier: sourceTemp.emittedName,
697
+ },
698
+ right: nullLiteral(),
699
+ },
700
+ thenStatement: {
701
+ kind: "blockStatement",
702
+ statements: [
703
+ {
704
+ kind: "returnStatement",
705
+ expression: { kind: "defaultExpression", type: dictTypeAst },
706
+ },
707
+ ],
708
+ },
709
+ },
710
+ {
711
+ kind: "localDeclarationStatement",
712
+ modifiers: [],
713
+ type: { kind: "varType" },
714
+ declarators: [
715
+ {
716
+ name: resultTemp.emittedName,
717
+ initializer: {
718
+ kind: "objectCreationExpression",
719
+ type: dictTypeAst,
720
+ arguments: [],
721
+ },
722
+ },
723
+ ],
724
+ },
725
+ {
726
+ kind: "foreachStatement",
727
+ isAwait: false,
728
+ type: { kind: "varType" },
729
+ identifier: entryTemp.emittedName,
730
+ expression: {
731
+ kind: "identifierExpression",
732
+ identifier: sourceTemp.emittedName,
733
+ },
734
+ body: {
735
+ kind: "blockStatement",
736
+ statements: [
737
+ {
738
+ kind: "expressionStatement",
739
+ expression: {
740
+ kind: "assignmentExpression",
741
+ operatorToken: "=",
742
+ left: {
743
+ kind: "elementAccessExpression",
744
+ expression: {
745
+ kind: "identifierExpression",
746
+ identifier: resultTemp.emittedName,
747
+ },
748
+ arguments: [
749
+ {
750
+ kind: "memberAccessExpression",
751
+ expression: {
752
+ kind: "identifierExpression",
753
+ identifier: entryTemp.emittedName,
754
+ },
755
+ memberName: "Key",
756
+ },
757
+ ],
758
+ },
759
+ right: adaptedValueAst,
760
+ },
761
+ },
762
+ ],
763
+ },
764
+ },
765
+ {
766
+ kind: "returnStatement",
767
+ expression: {
768
+ kind: "identifierExpression",
769
+ identifier: resultTemp.emittedName,
770
+ },
771
+ },
772
+ ];
773
+ return [
774
+ {
775
+ kind: "invocationExpression",
776
+ expression: {
777
+ kind: "parenthesizedExpression",
778
+ expression: {
779
+ kind: "castExpression",
780
+ type: buildDelegateType([], dictTypeAst),
781
+ expression: {
782
+ kind: "parenthesizedExpression",
783
+ expression: {
784
+ kind: "lambdaExpression",
785
+ isAsync: false,
786
+ parameters: [],
787
+ body: {
788
+ kind: "blockStatement",
789
+ statements,
790
+ },
791
+ },
792
+ },
793
+ },
794
+ },
795
+ arguments: [],
796
+ },
797
+ currentContext,
798
+ ];
799
+ }
800
+ }
801
+ return undefined;
802
+ };
20
803
  const getBareTypeParameterName = (type, context) => {
21
804
  if (type.kind === "typeParameterType")
22
805
  return type.name;
@@ -338,7 +1121,6 @@ const maybeUpcastDictionaryUnionValueAst = (expr, ast, context, expectedType) =>
338
1121
  if (matchingMemberIndex === -1)
339
1122
  return [ast, context];
340
1123
  const [unionValueTypeAst, ctx1] = emitTypeAst(expected.valueType, context);
341
- const unionTypeText = renderTypeAst(unionValueTypeAst);
342
1124
  const kvpId = "kvp";
343
1125
  const keySelector = {
344
1126
  kind: "lambdaExpression",
@@ -359,8 +1141,8 @@ const maybeUpcastDictionaryUnionValueAst = (expr, ast, context, expectedType) =>
359
1141
  expression: {
360
1142
  kind: "memberAccessExpression",
361
1143
  expression: {
362
- kind: "identifierExpression",
363
- identifier: unionTypeText,
1144
+ kind: "typeReferenceExpression",
1145
+ type: unionValueTypeAst,
364
1146
  },
365
1147
  memberName: `From${matchingMemberIndex}`,
366
1148
  },
@@ -378,8 +1160,7 @@ const maybeUpcastDictionaryUnionValueAst = (expr, ast, context, expectedType) =>
378
1160
  expression: {
379
1161
  kind: "memberAccessExpression",
380
1162
  expression: {
381
- kind: "identifierExpression",
382
- identifier: "global::System.Linq.Enumerable",
1163
+ ...identifierExpression("global::System.Linq.Enumerable"),
383
1164
  },
384
1165
  memberName: "ToDictionary",
385
1166
  },
@@ -477,7 +1258,9 @@ const emitTypeAssertion = (expr, context) => {
477
1258
  }
478
1259
  if (resolved.kind === "referenceType" && resolved.typeArguments?.length) {
479
1260
  const importBinding = ctx1.importBindings?.get(resolved.name);
480
- const clrName = importBinding?.kind === "type" ? importBinding.clrName : "";
1261
+ const clrName = importBinding?.kind === "type"
1262
+ ? (getIdentifierTypeName(importBinding.typeAst) ?? "")
1263
+ : "";
481
1264
  if (clrName.endsWith(".ExtensionMethods")) {
482
1265
  return true;
483
1266
  }
@@ -505,7 +1288,9 @@ const emitTypeAssertion = (expr, context) => {
505
1288
  }
506
1289
  if (target.kind === "referenceType" && target.typeArguments?.length) {
507
1290
  const importBinding = ctx.importBindings?.get(target.name);
508
- const clrName = importBinding?.kind === "type" ? importBinding.clrName : "";
1291
+ const clrName = importBinding?.kind === "type"
1292
+ ? (getIdentifierTypeName(importBinding.typeAst) ?? "")
1293
+ : "";
509
1294
  if (clrName.endsWith(".ExtensionMethods")) {
510
1295
  const shape = target.typeArguments[0];
511
1296
  if (shape)
@@ -594,13 +1379,7 @@ const emitDefaultOf = (expr, context) => {
594
1379
  /**
595
1380
  * Emit a nameof expression as a compile-time string literal using the authored TS name.
596
1381
  */
597
- const emitNameOf = (expr, context) => [
598
- {
599
- kind: "literalExpression",
600
- text: JSON.stringify(expr.name),
601
- },
602
- context,
603
- ];
1382
+ const emitNameOf = (expr, context) => [stringLiteral(expr.name), context];
604
1383
  /**
605
1384
  * Emit a sizeof expression as C# sizeof(T).
606
1385
  */
@@ -691,7 +1470,8 @@ export const emitExpressionAst = (expr, context, expectedType) => {
691
1470
  })();
692
1471
  const [castedAst, castedContext] = maybeCastNullishTypeParamAst(expr, ast, newContext, expectedType);
693
1472
  const [dictUpcastAst, dictUpcastContext] = maybeUpcastDictionaryUnionValueAst(expr, castedAst, castedContext, expectedType);
694
- const [stringAdjustedAst, stringAdjustedContext] = maybeConvertCharToStringAst(expr, dictUpcastAst, dictUpcastContext, expectedType);
1473
+ const [materializedAst, materializedContext] = tryAdaptStructuralExpressionAst(dictUpcastAst, expr.inferredType, dictUpcastContext, expectedType) ?? [dictUpcastAst, dictUpcastContext];
1474
+ const [stringAdjustedAst, stringAdjustedContext] = maybeConvertCharToStringAst(expr, materializedAst, materializedContext, expectedType);
695
1475
  return maybeUnwrapNullableValueTypeAst(expr, stringAdjustedAst, stringAdjustedContext, expectedType);
696
1476
  };
697
1477
  // Re-export commonly used functions from barrel