@tsonic/frontend 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/package.json +53 -0
  2. package/src/dependency-graph.ts +18 -0
  3. package/src/dotnet-metadata.ts +121 -0
  4. package/src/graph/builder.ts +81 -0
  5. package/src/graph/circular.ts +58 -0
  6. package/src/graph/extraction/exports.ts +55 -0
  7. package/src/graph/extraction/imports.ts +81 -0
  8. package/src/graph/extraction/index.ts +7 -0
  9. package/src/graph/extraction/orchestrator.ts +99 -0
  10. package/src/graph/extraction.ts +10 -0
  11. package/src/graph/helpers.ts +51 -0
  12. package/src/graph/index.ts +17 -0
  13. package/src/graph/types.ts +13 -0
  14. package/src/index.ts +80 -0
  15. package/src/ir/binding-resolution.test.ts +585 -0
  16. package/src/ir/builder/exports.ts +78 -0
  17. package/src/ir/builder/helpers.ts +27 -0
  18. package/src/ir/builder/imports.ts +153 -0
  19. package/src/ir/builder/index.ts +10 -0
  20. package/src/ir/builder/orchestrator.ts +178 -0
  21. package/src/ir/builder/statements.ts +55 -0
  22. package/src/ir/builder/types.ts +8 -0
  23. package/src/ir/builder/validation.ts +129 -0
  24. package/src/ir/builder.test.ts +581 -0
  25. package/src/ir/builder.ts +14 -0
  26. package/src/ir/converters/expressions/access.ts +99 -0
  27. package/src/ir/converters/expressions/calls.ts +137 -0
  28. package/src/ir/converters/expressions/collections.ts +84 -0
  29. package/src/ir/converters/expressions/functions.ts +62 -0
  30. package/src/ir/converters/expressions/helpers.ts +264 -0
  31. package/src/ir/converters/expressions/index.ts +43 -0
  32. package/src/ir/converters/expressions/literals.ts +22 -0
  33. package/src/ir/converters/expressions/operators.ts +147 -0
  34. package/src/ir/converters/expressions/other.ts +60 -0
  35. package/src/ir/converters/statements/control/blocks.ts +22 -0
  36. package/src/ir/converters/statements/control/conditionals.ts +67 -0
  37. package/src/ir/converters/statements/control/exceptions.ts +43 -0
  38. package/src/ir/converters/statements/control/index.ts +17 -0
  39. package/src/ir/converters/statements/control/loops.ts +99 -0
  40. package/src/ir/converters/statements/control.ts +17 -0
  41. package/src/ir/converters/statements/declarations/classes/constructors.ts +120 -0
  42. package/src/ir/converters/statements/declarations/classes/index.ts +12 -0
  43. package/src/ir/converters/statements/declarations/classes/methods.ts +61 -0
  44. package/src/ir/converters/statements/declarations/classes/orchestrator.ts +166 -0
  45. package/src/ir/converters/statements/declarations/classes/override-detection.ts +116 -0
  46. package/src/ir/converters/statements/declarations/classes/properties.ts +63 -0
  47. package/src/ir/converters/statements/declarations/classes.ts +6 -0
  48. package/src/ir/converters/statements/declarations/enums.ts +29 -0
  49. package/src/ir/converters/statements/declarations/functions.ts +39 -0
  50. package/src/ir/converters/statements/declarations/index.ts +14 -0
  51. package/src/ir/converters/statements/declarations/interfaces.ts +131 -0
  52. package/src/ir/converters/statements/declarations/registry.ts +45 -0
  53. package/src/ir/converters/statements/declarations/type-aliases.ts +25 -0
  54. package/src/ir/converters/statements/declarations/variables.ts +60 -0
  55. package/src/ir/converters/statements/declarations.ts +16 -0
  56. package/src/ir/converters/statements/helpers.ts +174 -0
  57. package/src/ir/converters/statements/index.ts +40 -0
  58. package/src/ir/expression-converter.ts +207 -0
  59. package/src/ir/generic-validator.ts +100 -0
  60. package/src/ir/hierarchical-bindings-e2e.test.ts +163 -0
  61. package/src/ir/index.ts +6 -0
  62. package/src/ir/statement-converter.ts +128 -0
  63. package/src/ir/type-converter/arrays.ts +20 -0
  64. package/src/ir/type-converter/converter.ts +10 -0
  65. package/src/ir/type-converter/functions.ts +22 -0
  66. package/src/ir/type-converter/index.ts +11 -0
  67. package/src/ir/type-converter/inference.ts +122 -0
  68. package/src/ir/type-converter/literals.ts +40 -0
  69. package/src/ir/type-converter/objects.ts +107 -0
  70. package/src/ir/type-converter/orchestrator.ts +85 -0
  71. package/src/ir/type-converter/patterns.ts +73 -0
  72. package/src/ir/type-converter/primitives.ts +57 -0
  73. package/src/ir/type-converter/references.ts +64 -0
  74. package/src/ir/type-converter/unions-intersections.ts +34 -0
  75. package/src/ir/type-converter.ts +13 -0
  76. package/src/ir/types/expressions.ts +215 -0
  77. package/src/ir/types/guards.ts +39 -0
  78. package/src/ir/types/helpers.ts +135 -0
  79. package/src/ir/types/index.ts +108 -0
  80. package/src/ir/types/ir-types.ts +96 -0
  81. package/src/ir/types/module.ts +57 -0
  82. package/src/ir/types/statements.ts +238 -0
  83. package/src/ir/types.ts +97 -0
  84. package/src/metadata/bindings-loader.test.ts +144 -0
  85. package/src/metadata/bindings-loader.ts +357 -0
  86. package/src/metadata/index.ts +15 -0
  87. package/src/metadata/library-loader.ts +153 -0
  88. package/src/metadata/loader.test.ts +156 -0
  89. package/src/metadata/loader.ts +382 -0
  90. package/src/program/bindings.test.ts +512 -0
  91. package/src/program/bindings.ts +253 -0
  92. package/src/program/config.ts +30 -0
  93. package/src/program/creation.ts +249 -0
  94. package/src/program/dependency-graph.ts +245 -0
  95. package/src/program/diagnostics.ts +103 -0
  96. package/src/program/index.ts +19 -0
  97. package/src/program/metadata.ts +68 -0
  98. package/src/program/queries.ts +18 -0
  99. package/src/program/types.ts +38 -0
  100. package/src/program.ts +13 -0
  101. package/src/resolver/dotnet-import-resolver.ts +226 -0
  102. package/src/resolver/import-resolution.ts +177 -0
  103. package/src/resolver/index.ts +18 -0
  104. package/src/resolver/namespace.test.ts +86 -0
  105. package/src/resolver/namespace.ts +42 -0
  106. package/src/resolver/naming.ts +38 -0
  107. package/src/resolver/path-resolution.ts +22 -0
  108. package/src/resolver/types.ts +15 -0
  109. package/src/resolver.test.ts +155 -0
  110. package/src/resolver.ts +14 -0
  111. package/src/symbol-table/builder.ts +114 -0
  112. package/src/symbol-table/creation.ts +42 -0
  113. package/src/symbol-table/helpers.ts +18 -0
  114. package/src/symbol-table/index.ts +13 -0
  115. package/src/symbol-table/queries.ts +42 -0
  116. package/src/symbol-table/types.ts +28 -0
  117. package/src/symbol-table.ts +14 -0
  118. package/src/types/bindings.ts +172 -0
  119. package/src/types/diagnostic.test.ts +164 -0
  120. package/src/types/diagnostic.ts +153 -0
  121. package/src/types/explicit-views.test.ts +113 -0
  122. package/src/types/explicit-views.ts +218 -0
  123. package/src/types/metadata.ts +229 -0
  124. package/src/types/module.ts +99 -0
  125. package/src/types/nested-types.test.ts +194 -0
  126. package/src/types/nested-types.ts +215 -0
  127. package/src/types/parameter-modifiers.ts +173 -0
  128. package/src/types/ref-parameters.test.ts +192 -0
  129. package/src/types/ref-parameters.ts +268 -0
  130. package/src/types/result.test.ts +157 -0
  131. package/src/types/result.ts +48 -0
  132. package/src/types/support-types.test.ts +81 -0
  133. package/src/types/support-types.ts +288 -0
  134. package/src/types/test-harness.ts +180 -0
  135. package/src/validation/exports.ts +98 -0
  136. package/src/validation/features.ts +89 -0
  137. package/src/validation/generics.ts +40 -0
  138. package/src/validation/helpers.ts +31 -0
  139. package/src/validation/imports.ts +97 -0
  140. package/src/validation/index.ts +11 -0
  141. package/src/validation/orchestrator.ts +51 -0
  142. package/src/validation/static-safety.ts +267 -0
  143. package/src/validator.test.ts +468 -0
  144. package/src/validator.ts +15 -0
  145. package/tsconfig.json +13 -0
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Variable declaration converter
3
+ */
4
+
5
+ import * as ts from "typescript";
6
+ import { IrVariableDeclaration } from "../../../types.js";
7
+ import { convertExpression } from "../../../expression-converter.js";
8
+ import {
9
+ convertType,
10
+ convertBindingName,
11
+ inferType,
12
+ } from "../../../type-converter.js";
13
+ import { hasExportModifier } from "../helpers.js";
14
+
15
+ /**
16
+ * Get the IR type for a variable declaration.
17
+ * Uses explicit annotation if present, otherwise infers from TypeChecker.
18
+ */
19
+ const getDeclarationType = (
20
+ decl: ts.VariableDeclaration,
21
+ checker: ts.TypeChecker,
22
+ needsExplicitType: boolean
23
+ ) => {
24
+ // If there's an explicit type annotation, use it
25
+ if (decl.type) {
26
+ return convertType(decl.type, checker);
27
+ }
28
+ // If we need an explicit type (for module-level exports), infer it
29
+ if (needsExplicitType) {
30
+ return inferType(decl, checker);
31
+ }
32
+ return undefined;
33
+ };
34
+
35
+ /**
36
+ * Convert variable statement
37
+ */
38
+ export const convertVariableStatement = (
39
+ node: ts.VariableStatement,
40
+ checker: ts.TypeChecker
41
+ ): IrVariableDeclaration => {
42
+ const isConst = !!(node.declarationList.flags & ts.NodeFlags.Const);
43
+ const isLet = !!(node.declarationList.flags & ts.NodeFlags.Let);
44
+ const declarationKind = isConst ? "const" : isLet ? "let" : "var";
45
+ const isExported = hasExportModifier(node);
46
+
47
+ return {
48
+ kind: "variableDeclaration",
49
+ declarationKind,
50
+ declarations: node.declarationList.declarations.map((decl) => ({
51
+ kind: "variableDeclarator",
52
+ name: convertBindingName(decl.name),
53
+ type: getDeclarationType(decl, checker, isExported),
54
+ initializer: decl.initializer
55
+ ? convertExpression(decl.initializer, checker)
56
+ : undefined,
57
+ })),
58
+ isExported,
59
+ };
60
+ };
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Declaration converters (variables, functions, classes, interfaces, enums, type aliases)
3
+ * Main dispatcher - re-exports from declarations/ subdirectory
4
+ */
5
+
6
+ export {
7
+ setMetadataRegistry,
8
+ setBindingRegistry,
9
+ convertVariableStatement,
10
+ convertFunctionDeclaration,
11
+ convertClassDeclaration,
12
+ convertInterfaceDeclaration,
13
+ convertInterfaceMember,
14
+ convertEnumDeclaration,
15
+ convertTypeAliasDeclaration,
16
+ } from "./declarations/index.js";
@@ -0,0 +1,174 @@
1
+ /**
2
+ * Helper utilities for statement conversion
3
+ */
4
+
5
+ import * as ts from "typescript";
6
+ import {
7
+ IrParameter,
8
+ IrAccessibility,
9
+ IrTypeParameter,
10
+ IrInterfaceMember,
11
+ IrVariableDeclaration,
12
+ } from "../../types.js";
13
+ import { convertType, convertBindingName } from "../../type-converter.js";
14
+ import { convertExpression } from "../../expression-converter.js";
15
+ import { convertInterfaceMember } from "./declarations.js";
16
+
17
+ /**
18
+ * Convert TypeScript type parameters to IR, detecting structural constraints
19
+ */
20
+ export const convertTypeParameters = (
21
+ typeParameters: readonly ts.TypeParameterDeclaration[] | undefined,
22
+ checker: ts.TypeChecker
23
+ ): readonly IrTypeParameter[] | undefined => {
24
+ if (!typeParameters || typeParameters.length === 0) {
25
+ return undefined;
26
+ }
27
+
28
+ return typeParameters.map((tp) => {
29
+ const name = tp.name.text;
30
+ const constraint = tp.constraint
31
+ ? convertType(tp.constraint, checker)
32
+ : undefined;
33
+ const defaultType = tp.default
34
+ ? convertType(tp.default, checker)
35
+ : undefined;
36
+
37
+ // Check if constraint is structural (object literal type)
38
+ const isStructural = tp.constraint && ts.isTypeLiteralNode(tp.constraint);
39
+
40
+ // Extract structural members if it's a structural constraint
41
+ const structuralMembers =
42
+ isStructural && tp.constraint && ts.isTypeLiteralNode(tp.constraint)
43
+ ? tp.constraint.members
44
+ .map((member) => convertInterfaceMember(member, checker))
45
+ .filter((m): m is IrInterfaceMember => m !== null)
46
+ : undefined;
47
+
48
+ return {
49
+ kind: "typeParameter" as const,
50
+ name,
51
+ constraint,
52
+ default: defaultType,
53
+ variance: undefined, // TypeScript doesn't expose variance directly
54
+ isStructuralConstraint: isStructural,
55
+ structuralMembers,
56
+ };
57
+ });
58
+ };
59
+
60
+ /**
61
+ * Convert parameters for functions and methods
62
+ */
63
+ export const convertParameters = (
64
+ parameters: ts.NodeArray<ts.ParameterDeclaration>,
65
+ checker: ts.TypeChecker
66
+ ): readonly IrParameter[] => {
67
+ return parameters.map((param) => {
68
+ let passing: "value" | "ref" | "out" | "in" = "value";
69
+ let actualType: ts.TypeNode | undefined = param.type;
70
+
71
+ // Detect ref<T>, out<T>, in<T> wrapper types
72
+ if (
73
+ param.type &&
74
+ ts.isTypeReferenceNode(param.type) &&
75
+ ts.isIdentifier(param.type.typeName)
76
+ ) {
77
+ const typeName = param.type.typeName.text;
78
+ if (
79
+ (typeName === "ref" || typeName === "out" || typeName === "in") &&
80
+ param.type.typeArguments &&
81
+ param.type.typeArguments.length > 0
82
+ ) {
83
+ // Set passing mode
84
+ passing = typeName === "in" ? "in" : typeName;
85
+ // Extract wrapped type
86
+ actualType = param.type.typeArguments[0];
87
+ }
88
+ }
89
+
90
+ return {
91
+ kind: "parameter",
92
+ pattern: convertBindingName(param.name),
93
+ type: actualType ? convertType(actualType, checker) : undefined,
94
+ initializer: param.initializer
95
+ ? convertExpression(param.initializer, checker)
96
+ : undefined,
97
+ isOptional: !!param.questionToken,
98
+ isRest: !!param.dotDotDotToken,
99
+ passing,
100
+ };
101
+ });
102
+ };
103
+
104
+ /**
105
+ * Convert variable declaration list (used in for loops)
106
+ */
107
+ export const convertVariableDeclarationList = (
108
+ node: ts.VariableDeclarationList,
109
+ checker: ts.TypeChecker
110
+ ): IrVariableDeclaration => {
111
+ const isConst = !!(node.flags & ts.NodeFlags.Const);
112
+ const isLet = !!(node.flags & ts.NodeFlags.Let);
113
+ const declarationKind = isConst ? "const" : isLet ? "let" : "var";
114
+
115
+ return {
116
+ kind: "variableDeclaration",
117
+ declarationKind,
118
+ declarations: node.declarations.map((decl) => ({
119
+ kind: "variableDeclarator",
120
+ name: convertBindingName(decl.name),
121
+ type: decl.type ? convertType(decl.type, checker) : undefined,
122
+ initializer: decl.initializer
123
+ ? convertExpression(decl.initializer, checker)
124
+ : undefined,
125
+ })),
126
+ isExported: false,
127
+ };
128
+ };
129
+
130
+ /**
131
+ * Check if node has export modifier
132
+ */
133
+ export const hasExportModifier = (node: ts.Node): boolean => {
134
+ if (!ts.canHaveModifiers(node)) return false;
135
+ const modifiers = ts.getModifiers(node);
136
+ return (
137
+ modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword) ?? false
138
+ );
139
+ };
140
+
141
+ /**
142
+ * Check if node has static modifier
143
+ */
144
+ export const hasStaticModifier = (node: ts.Node): boolean => {
145
+ if (!ts.canHaveModifiers(node)) return false;
146
+ const modifiers = ts.getModifiers(node);
147
+ return (
148
+ modifiers?.some((m) => m.kind === ts.SyntaxKind.StaticKeyword) ?? false
149
+ );
150
+ };
151
+
152
+ /**
153
+ * Check if node has readonly modifier
154
+ */
155
+ export const hasReadonlyModifier = (node: ts.Node): boolean => {
156
+ if (!ts.canHaveModifiers(node)) return false;
157
+ const modifiers = ts.getModifiers(node);
158
+ return (
159
+ modifiers?.some((m) => m.kind === ts.SyntaxKind.ReadonlyKeyword) ?? false
160
+ );
161
+ };
162
+
163
+ /**
164
+ * Get accessibility modifier
165
+ */
166
+ export const getAccessibility = (node: ts.Node): IrAccessibility => {
167
+ if (!ts.canHaveModifiers(node)) return "public";
168
+ const modifiers = ts.getModifiers(node);
169
+ if (modifiers?.some((m) => m.kind === ts.SyntaxKind.PrivateKeyword))
170
+ return "private";
171
+ if (modifiers?.some((m) => m.kind === ts.SyntaxKind.ProtectedKeyword))
172
+ return "protected";
173
+ return "public";
174
+ };
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Statement converters barrel exports
3
+ */
4
+
5
+ // Helpers
6
+ export {
7
+ convertTypeParameters,
8
+ convertParameters,
9
+ convertVariableDeclarationList,
10
+ hasExportModifier,
11
+ hasStaticModifier,
12
+ hasReadonlyModifier,
13
+ getAccessibility,
14
+ } from "./helpers.js";
15
+
16
+ // Control flow converters
17
+ export {
18
+ convertIfStatement,
19
+ convertWhileStatement,
20
+ convertForStatement,
21
+ convertForOfStatement,
22
+ convertForInStatement,
23
+ convertSwitchStatement,
24
+ convertSwitchCase,
25
+ convertTryStatement,
26
+ convertCatchClause,
27
+ convertBlockStatement,
28
+ } from "./control.js";
29
+
30
+ // Declaration converters
31
+ export {
32
+ setMetadataRegistry,
33
+ convertVariableStatement,
34
+ convertFunctionDeclaration,
35
+ convertClassDeclaration,
36
+ convertInterfaceDeclaration,
37
+ convertInterfaceMember,
38
+ convertEnumDeclaration,
39
+ convertTypeAliasDeclaration,
40
+ } from "./declarations.js";
@@ -0,0 +1,207 @@
1
+ /**
2
+ * Expression converter - TypeScript AST to IR expressions
3
+ * Main dispatcher - delegates to specialized modules
4
+ */
5
+
6
+ import * as ts from "typescript";
7
+ import { IrExpression } from "./types.js";
8
+ import { getBindingRegistry } from "./converters/statements/declarations/registry.js";
9
+ import { convertType } from "./type-converter.js";
10
+
11
+ // Import expression converters from specialized modules
12
+ import { convertLiteral } from "./converters/expressions/literals.js";
13
+ import {
14
+ convertArrayLiteral,
15
+ convertObjectLiteral,
16
+ } from "./converters/expressions/collections.js";
17
+ import { convertMemberExpression } from "./converters/expressions/access.js";
18
+ import {
19
+ convertCallExpression,
20
+ convertNewExpression,
21
+ } from "./converters/expressions/calls.js";
22
+ import {
23
+ convertBinaryExpression,
24
+ convertUnaryExpression,
25
+ convertUpdateExpression,
26
+ } from "./converters/expressions/operators.js";
27
+ import {
28
+ convertFunctionExpression,
29
+ convertArrowFunction,
30
+ } from "./converters/expressions/functions.js";
31
+ import {
32
+ convertConditionalExpression,
33
+ convertTemplateLiteral,
34
+ } from "./converters/expressions/other.js";
35
+ import { getInferredType } from "./converters/expressions/helpers.js";
36
+
37
+ /**
38
+ * Main expression conversion dispatcher
39
+ * Converts TypeScript expression nodes to IR expressions
40
+ */
41
+ export const convertExpression = (
42
+ node: ts.Expression,
43
+ checker: ts.TypeChecker
44
+ ): IrExpression => {
45
+ const inferredType = getInferredType(node, checker);
46
+
47
+ if (ts.isStringLiteral(node) || ts.isNumericLiteral(node)) {
48
+ return convertLiteral(node, checker);
49
+ }
50
+ if (
51
+ node.kind === ts.SyntaxKind.TrueKeyword ||
52
+ node.kind === ts.SyntaxKind.FalseKeyword
53
+ ) {
54
+ return {
55
+ kind: "literal",
56
+ value: node.kind === ts.SyntaxKind.TrueKeyword,
57
+ raw: node.getText(),
58
+ inferredType,
59
+ };
60
+ }
61
+ if (node.kind === ts.SyntaxKind.NullKeyword) {
62
+ return { kind: "literal", value: null, raw: "null", inferredType };
63
+ }
64
+ if (
65
+ node.kind === ts.SyntaxKind.UndefinedKeyword ||
66
+ ts.isVoidExpression(node)
67
+ ) {
68
+ return {
69
+ kind: "literal",
70
+ value: undefined,
71
+ raw: "undefined",
72
+ inferredType,
73
+ };
74
+ }
75
+ if (ts.isIdentifier(node)) {
76
+ // Check if this identifier is bound to a CLR type (e.g., console, Math, etc.)
77
+ const binding = getBindingRegistry().getBinding(node.text);
78
+ if (binding && binding.kind === "global") {
79
+ return {
80
+ kind: "identifier",
81
+ name: node.text,
82
+ inferredType,
83
+ resolvedClrType: binding.type,
84
+ resolvedAssembly: binding.assembly,
85
+ csharpName: binding.csharpName, // Optional C# name from binding
86
+ };
87
+ }
88
+ return { kind: "identifier", name: node.text, inferredType };
89
+ }
90
+ if (ts.isArrayLiteralExpression(node)) {
91
+ return convertArrayLiteral(node, checker);
92
+ }
93
+ if (ts.isObjectLiteralExpression(node)) {
94
+ return convertObjectLiteral(node, checker);
95
+ }
96
+ if (
97
+ ts.isPropertyAccessExpression(node) ||
98
+ ts.isElementAccessExpression(node)
99
+ ) {
100
+ return convertMemberExpression(node, checker);
101
+ }
102
+ if (ts.isCallExpression(node)) {
103
+ return convertCallExpression(node, checker);
104
+ }
105
+ if (ts.isNewExpression(node)) {
106
+ return convertNewExpression(node, checker);
107
+ }
108
+ if (ts.isBinaryExpression(node)) {
109
+ return convertBinaryExpression(node, checker);
110
+ }
111
+ if (ts.isPrefixUnaryExpression(node)) {
112
+ return convertUnaryExpression(node, checker);
113
+ }
114
+ if (ts.isPostfixUnaryExpression(node)) {
115
+ return convertUpdateExpression(node, checker);
116
+ }
117
+ if (ts.isTypeOfExpression(node)) {
118
+ return {
119
+ kind: "unary",
120
+ operator: "typeof",
121
+ expression: convertExpression(node.expression, checker),
122
+ inferredType,
123
+ };
124
+ }
125
+ if (ts.isVoidExpression(node)) {
126
+ return {
127
+ kind: "unary",
128
+ operator: "void",
129
+ expression: convertExpression(node.expression, checker),
130
+ inferredType,
131
+ };
132
+ }
133
+ if (ts.isDeleteExpression(node)) {
134
+ return {
135
+ kind: "unary",
136
+ operator: "delete",
137
+ expression: convertExpression(node.expression, checker),
138
+ inferredType,
139
+ };
140
+ }
141
+ if (ts.isConditionalExpression(node)) {
142
+ return convertConditionalExpression(node, checker);
143
+ }
144
+ if (ts.isFunctionExpression(node)) {
145
+ return convertFunctionExpression(node, checker);
146
+ }
147
+ if (ts.isArrowFunction(node)) {
148
+ return convertArrowFunction(node, checker);
149
+ }
150
+ if (
151
+ ts.isTemplateExpression(node) ||
152
+ ts.isNoSubstitutionTemplateLiteral(node)
153
+ ) {
154
+ return convertTemplateLiteral(node, checker);
155
+ }
156
+ if (ts.isSpreadElement(node)) {
157
+ return {
158
+ kind: "spread",
159
+ expression: convertExpression(node.expression, checker),
160
+ inferredType,
161
+ };
162
+ }
163
+ if (node.kind === ts.SyntaxKind.ThisKeyword) {
164
+ return { kind: "this", inferredType };
165
+ }
166
+ if (ts.isAwaitExpression(node)) {
167
+ return {
168
+ kind: "await",
169
+ expression: convertExpression(node.expression, checker),
170
+ inferredType,
171
+ };
172
+ }
173
+ if (ts.isYieldExpression(node)) {
174
+ return {
175
+ kind: "yield",
176
+ expression: node.expression
177
+ ? convertExpression(node.expression, checker)
178
+ : undefined,
179
+ delegate: !!node.asteriskToken,
180
+ inferredType,
181
+ };
182
+ }
183
+ if (ts.isParenthesizedExpression(node)) {
184
+ return convertExpression(node.expression, checker);
185
+ }
186
+ if (ts.isAsExpression(node) || ts.isTypeAssertionExpression(node)) {
187
+ // Convert the inner expression
188
+ const innerExpr = convertExpression(
189
+ ts.isAsExpression(node) ? node.expression : node.expression,
190
+ checker
191
+ );
192
+ // Preserve the asserted type - this is needed for casts like `x as int`
193
+ const assertedTypeNode = ts.isAsExpression(node) ? node.type : node.type;
194
+ const assertedType = convertType(assertedTypeNode, checker);
195
+ return { ...innerExpr, inferredType: assertedType };
196
+ }
197
+
198
+ // Fallback - treat as identifier
199
+ return { kind: "identifier", name: node.getText(), inferredType };
200
+ };
201
+
202
+ // Re-export commonly used functions for backward compatibility
203
+ export {
204
+ getInferredType,
205
+ extractTypeArguments,
206
+ checkIfRequiresSpecialization,
207
+ } from "./converters/expressions/helpers.js";
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Generic validation - detect truly unsupported generic patterns
3
+ *
4
+ * NOTE: Many previously-blocked constructs are now handled via:
5
+ * - Monomorphisation for finite specializations
6
+ * - CRTP pattern for `this` typing
7
+ * - Tuple specialisations for variadic parameters
8
+ * - Structural adapters for mapped/conditional types
9
+ *
10
+ * Only constructs with NO static mapping remain as errors.
11
+ */
12
+
13
+ import * as ts from "typescript";
14
+ import {
15
+ Diagnostic,
16
+ createDiagnostic,
17
+ SourceLocation,
18
+ } from "../types/diagnostic.js";
19
+
20
+ /**
21
+ * Get source location from TypeScript node
22
+ */
23
+ const getLocation = (
24
+ node: ts.Node,
25
+ sourceFile: ts.SourceFile
26
+ ): SourceLocation => {
27
+ const { line, character } = sourceFile.getLineAndCharacterOfPosition(
28
+ node.getStart()
29
+ );
30
+ return {
31
+ file: sourceFile.fileName,
32
+ line: line + 1,
33
+ column: character + 1,
34
+ length: node.getWidth(),
35
+ };
36
+ };
37
+
38
+ /**
39
+ * Check for symbol index signatures (TSN7203)
40
+ *
41
+ * Symbol keys have no static C# mapping and must be rejected.
42
+ */
43
+ export const checkForSymbolIndexSignature = (
44
+ node: ts.IndexSignatureDeclaration,
45
+ sourceFile: ts.SourceFile
46
+ ): Diagnostic | null => {
47
+ // Check if the parameter type is symbol
48
+ if (node.parameters.length > 0) {
49
+ const param = node.parameters[0];
50
+ if (param && param.type) {
51
+ // Check for symbol keyword type
52
+ if (param.type.kind === ts.SyntaxKind.SymbolKeyword) {
53
+ return createDiagnostic(
54
+ "TSN7203",
55
+ "error",
56
+ "Symbol keys are not supported in C#",
57
+ getLocation(node, sourceFile),
58
+ "Use string keys instead of symbol keys"
59
+ );
60
+ }
61
+
62
+ // Also check for type reference to 'symbol'
63
+ if (ts.isTypeReferenceNode(param.type)) {
64
+ if (
65
+ ts.isIdentifier(param.type.typeName) &&
66
+ param.type.typeName.text === "symbol"
67
+ ) {
68
+ return createDiagnostic(
69
+ "TSN7203",
70
+ "error",
71
+ "Symbol keys are not supported in C#",
72
+ getLocation(node, sourceFile),
73
+ "Use string keys instead of symbol keys"
74
+ );
75
+ }
76
+ }
77
+ }
78
+ }
79
+
80
+ return null;
81
+ };
82
+
83
+ /**
84
+ * REMOVED CHECKS (now handled by implementation):
85
+ *
86
+ * - checkForInferKeyword (TSN7102)
87
+ * Conditional types with infer are handled via monomorphisation
88
+ *
89
+ * - checkForRecursiveMappedType (TSN7101)
90
+ * Finite mapped types are specialized; unbounded cases get adapters
91
+ *
92
+ * - checkForThisType (TSN7103)
93
+ * `this` typing is handled via CRTP pattern
94
+ *
95
+ * - checkForVariadicTypeParameter (TSN7104)
96
+ * Variadic parameters are handled via tuple specialisations
97
+ *
98
+ * - checkForRecursiveStructuralAlias (TSN7201)
99
+ * Recursive structural aliases emit as C# classes with nullable refs
100
+ */