@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.
- package/package.json +53 -0
- package/src/dependency-graph.ts +18 -0
- package/src/dotnet-metadata.ts +121 -0
- package/src/graph/builder.ts +81 -0
- package/src/graph/circular.ts +58 -0
- package/src/graph/extraction/exports.ts +55 -0
- package/src/graph/extraction/imports.ts +81 -0
- package/src/graph/extraction/index.ts +7 -0
- package/src/graph/extraction/orchestrator.ts +99 -0
- package/src/graph/extraction.ts +10 -0
- package/src/graph/helpers.ts +51 -0
- package/src/graph/index.ts +17 -0
- package/src/graph/types.ts +13 -0
- package/src/index.ts +80 -0
- package/src/ir/binding-resolution.test.ts +585 -0
- package/src/ir/builder/exports.ts +78 -0
- package/src/ir/builder/helpers.ts +27 -0
- package/src/ir/builder/imports.ts +153 -0
- package/src/ir/builder/index.ts +10 -0
- package/src/ir/builder/orchestrator.ts +178 -0
- package/src/ir/builder/statements.ts +55 -0
- package/src/ir/builder/types.ts +8 -0
- package/src/ir/builder/validation.ts +129 -0
- package/src/ir/builder.test.ts +581 -0
- package/src/ir/builder.ts +14 -0
- package/src/ir/converters/expressions/access.ts +99 -0
- package/src/ir/converters/expressions/calls.ts +137 -0
- package/src/ir/converters/expressions/collections.ts +84 -0
- package/src/ir/converters/expressions/functions.ts +62 -0
- package/src/ir/converters/expressions/helpers.ts +264 -0
- package/src/ir/converters/expressions/index.ts +43 -0
- package/src/ir/converters/expressions/literals.ts +22 -0
- package/src/ir/converters/expressions/operators.ts +147 -0
- package/src/ir/converters/expressions/other.ts +60 -0
- package/src/ir/converters/statements/control/blocks.ts +22 -0
- package/src/ir/converters/statements/control/conditionals.ts +67 -0
- package/src/ir/converters/statements/control/exceptions.ts +43 -0
- package/src/ir/converters/statements/control/index.ts +17 -0
- package/src/ir/converters/statements/control/loops.ts +99 -0
- package/src/ir/converters/statements/control.ts +17 -0
- package/src/ir/converters/statements/declarations/classes/constructors.ts +120 -0
- package/src/ir/converters/statements/declarations/classes/index.ts +12 -0
- package/src/ir/converters/statements/declarations/classes/methods.ts +61 -0
- package/src/ir/converters/statements/declarations/classes/orchestrator.ts +166 -0
- package/src/ir/converters/statements/declarations/classes/override-detection.ts +116 -0
- package/src/ir/converters/statements/declarations/classes/properties.ts +63 -0
- package/src/ir/converters/statements/declarations/classes.ts +6 -0
- package/src/ir/converters/statements/declarations/enums.ts +29 -0
- package/src/ir/converters/statements/declarations/functions.ts +39 -0
- package/src/ir/converters/statements/declarations/index.ts +14 -0
- package/src/ir/converters/statements/declarations/interfaces.ts +131 -0
- package/src/ir/converters/statements/declarations/registry.ts +45 -0
- package/src/ir/converters/statements/declarations/type-aliases.ts +25 -0
- package/src/ir/converters/statements/declarations/variables.ts +60 -0
- package/src/ir/converters/statements/declarations.ts +16 -0
- package/src/ir/converters/statements/helpers.ts +174 -0
- package/src/ir/converters/statements/index.ts +40 -0
- package/src/ir/expression-converter.ts +207 -0
- package/src/ir/generic-validator.ts +100 -0
- package/src/ir/hierarchical-bindings-e2e.test.ts +163 -0
- package/src/ir/index.ts +6 -0
- package/src/ir/statement-converter.ts +128 -0
- package/src/ir/type-converter/arrays.ts +20 -0
- package/src/ir/type-converter/converter.ts +10 -0
- package/src/ir/type-converter/functions.ts +22 -0
- package/src/ir/type-converter/index.ts +11 -0
- package/src/ir/type-converter/inference.ts +122 -0
- package/src/ir/type-converter/literals.ts +40 -0
- package/src/ir/type-converter/objects.ts +107 -0
- package/src/ir/type-converter/orchestrator.ts +85 -0
- package/src/ir/type-converter/patterns.ts +73 -0
- package/src/ir/type-converter/primitives.ts +57 -0
- package/src/ir/type-converter/references.ts +64 -0
- package/src/ir/type-converter/unions-intersections.ts +34 -0
- package/src/ir/type-converter.ts +13 -0
- package/src/ir/types/expressions.ts +215 -0
- package/src/ir/types/guards.ts +39 -0
- package/src/ir/types/helpers.ts +135 -0
- package/src/ir/types/index.ts +108 -0
- package/src/ir/types/ir-types.ts +96 -0
- package/src/ir/types/module.ts +57 -0
- package/src/ir/types/statements.ts +238 -0
- package/src/ir/types.ts +97 -0
- package/src/metadata/bindings-loader.test.ts +144 -0
- package/src/metadata/bindings-loader.ts +357 -0
- package/src/metadata/index.ts +15 -0
- package/src/metadata/library-loader.ts +153 -0
- package/src/metadata/loader.test.ts +156 -0
- package/src/metadata/loader.ts +382 -0
- package/src/program/bindings.test.ts +512 -0
- package/src/program/bindings.ts +253 -0
- package/src/program/config.ts +30 -0
- package/src/program/creation.ts +249 -0
- package/src/program/dependency-graph.ts +245 -0
- package/src/program/diagnostics.ts +103 -0
- package/src/program/index.ts +19 -0
- package/src/program/metadata.ts +68 -0
- package/src/program/queries.ts +18 -0
- package/src/program/types.ts +38 -0
- package/src/program.ts +13 -0
- package/src/resolver/dotnet-import-resolver.ts +226 -0
- package/src/resolver/import-resolution.ts +177 -0
- package/src/resolver/index.ts +18 -0
- package/src/resolver/namespace.test.ts +86 -0
- package/src/resolver/namespace.ts +42 -0
- package/src/resolver/naming.ts +38 -0
- package/src/resolver/path-resolution.ts +22 -0
- package/src/resolver/types.ts +15 -0
- package/src/resolver.test.ts +155 -0
- package/src/resolver.ts +14 -0
- package/src/symbol-table/builder.ts +114 -0
- package/src/symbol-table/creation.ts +42 -0
- package/src/symbol-table/helpers.ts +18 -0
- package/src/symbol-table/index.ts +13 -0
- package/src/symbol-table/queries.ts +42 -0
- package/src/symbol-table/types.ts +28 -0
- package/src/symbol-table.ts +14 -0
- package/src/types/bindings.ts +172 -0
- package/src/types/diagnostic.test.ts +164 -0
- package/src/types/diagnostic.ts +153 -0
- package/src/types/explicit-views.test.ts +113 -0
- package/src/types/explicit-views.ts +218 -0
- package/src/types/metadata.ts +229 -0
- package/src/types/module.ts +99 -0
- package/src/types/nested-types.test.ts +194 -0
- package/src/types/nested-types.ts +215 -0
- package/src/types/parameter-modifiers.ts +173 -0
- package/src/types/ref-parameters.test.ts +192 -0
- package/src/types/ref-parameters.ts +268 -0
- package/src/types/result.test.ts +157 -0
- package/src/types/result.ts +48 -0
- package/src/types/support-types.test.ts +81 -0
- package/src/types/support-types.ts +288 -0
- package/src/types/test-harness.ts +180 -0
- package/src/validation/exports.ts +98 -0
- package/src/validation/features.ts +89 -0
- package/src/validation/generics.ts +40 -0
- package/src/validation/helpers.ts +31 -0
- package/src/validation/imports.ts +97 -0
- package/src/validation/index.ts +11 -0
- package/src/validation/orchestrator.ts +51 -0
- package/src/validation/static-safety.ts +267 -0
- package/src/validator.test.ts +468 -0
- package/src/validator.ts +15 -0
- 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
|
+
*/
|