@tsonic/frontend 0.0.62 → 0.0.64
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/dependency-graph.d.ts +1 -1
- package/dist/dependency-graph.d.ts.map +1 -1
- package/dist/dependency-graph.js +1 -1
- package/dist/dependency-graph.js.map +1 -1
- package/dist/dotnet-metadata.d.ts +0 -12
- package/dist/dotnet-metadata.d.ts.map +1 -1
- package/dist/dotnet-metadata.js +0 -24
- package/dist/dotnet-metadata.js.map +1 -1
- package/dist/generic-function-values.d.ts +11 -0
- package/dist/generic-function-values.d.ts.map +1 -0
- package/dist/generic-function-values.js +243 -0
- package/dist/generic-function-values.js.map +1 -0
- package/dist/generic-function-values.test.d.ts +2 -0
- package/dist/generic-function-values.test.d.ts.map +1 -0
- package/dist/generic-function-values.test.js +256 -0
- package/dist/generic-function-values.test.js.map +1 -0
- package/dist/graph/extraction/imports.d.ts +5 -0
- package/dist/graph/extraction/imports.d.ts.map +1 -1
- package/dist/graph/extraction/imports.js +39 -1
- package/dist/graph/extraction/imports.js.map +1 -1
- package/dist/graph/extraction/index.d.ts +1 -1
- package/dist/graph/extraction/index.d.ts.map +1 -1
- package/dist/graph/extraction/index.js +1 -1
- package/dist/graph/extraction/index.js.map +1 -1
- package/dist/graph/extraction/orchestrator.d.ts.map +1 -1
- package/dist/graph/extraction/orchestrator.js +16 -2
- package/dist/graph/extraction/orchestrator.js.map +1 -1
- package/dist/graph/extraction.d.ts +1 -1
- package/dist/graph/extraction.d.ts.map +1 -1
- package/dist/graph/extraction.js +1 -1
- package/dist/graph/extraction.js.map +1 -1
- package/dist/ir/binding/binding-factory.d.ts +17 -0
- package/dist/ir/binding/binding-factory.d.ts.map +1 -0
- package/dist/ir/binding/binding-factory.js +765 -0
- package/dist/ir/binding/binding-factory.js.map +1 -0
- package/dist/ir/binding/binding-helpers.d.ts +90 -0
- package/dist/ir/binding/binding-helpers.d.ts.map +1 -0
- package/dist/ir/binding/binding-helpers.js +387 -0
- package/dist/ir/binding/binding-helpers.js.map +1 -0
- package/dist/ir/binding/binding-types.d.ts +203 -0
- package/dist/ir/binding/binding-types.d.ts.map +1 -0
- package/dist/ir/binding/binding-types.js +9 -0
- package/dist/ir/binding/binding-types.js.map +1 -0
- package/dist/ir/binding/index.d.ts +4 -158
- package/dist/ir/binding/index.d.ts.map +1 -1
- package/dist/ir/binding/index.js +3 -1134
- package/dist/ir/binding/index.js.map +1 -1
- package/dist/ir/binding-resolution.test.js +248 -0
- package/dist/ir/binding-resolution.test.js.map +1 -1
- package/dist/ir/builder/imports.d.ts.map +1 -1
- package/dist/ir/builder/imports.js +8 -1
- package/dist/ir/builder/imports.js.map +1 -1
- package/dist/ir/builder.test.js +360 -0
- package/dist/ir/builder.test.js.map +1 -1
- package/dist/ir/converters/anonymous-synthesis.d.ts +3 -3
- package/dist/ir/converters/anonymous-synthesis.d.ts.map +1 -1
- package/dist/ir/converters/anonymous-synthesis.js +45 -8
- package/dist/ir/converters/anonymous-synthesis.js.map +1 -1
- package/dist/ir/converters/expressions/access/access-converter.d.ts +14 -0
- package/dist/ir/converters/expressions/access/access-converter.d.ts.map +1 -0
- package/dist/ir/converters/expressions/access/access-converter.js +141 -0
- package/dist/ir/converters/expressions/access/access-converter.js.map +1 -0
- package/dist/ir/converters/expressions/access/binding-resolution.d.ts +35 -0
- package/dist/ir/converters/expressions/access/binding-resolution.d.ts.map +1 -0
- package/dist/ir/converters/expressions/access/binding-resolution.js +447 -0
- package/dist/ir/converters/expressions/access/binding-resolution.js.map +1 -0
- package/dist/ir/converters/expressions/access/member-resolution.d.ts +67 -0
- package/dist/ir/converters/expressions/access/member-resolution.d.ts.map +1 -0
- package/dist/ir/converters/expressions/access/member-resolution.js +262 -0
- package/dist/ir/converters/expressions/access/member-resolution.js.map +1 -0
- package/dist/ir/converters/expressions/access.d.ts +1 -7
- package/dist/ir/converters/expressions/access.d.ts.map +1 -1
- package/dist/ir/converters/expressions/access.js +1 -720
- package/dist/ir/converters/expressions/access.js.map +1 -1
- package/dist/ir/converters/expressions/calls/call-converter.d.ts +23 -0
- package/dist/ir/converters/expressions/calls/call-converter.d.ts.map +1 -0
- package/dist/ir/converters/expressions/calls/call-converter.js +526 -0
- package/dist/ir/converters/expressions/calls/call-converter.js.map +1 -0
- package/dist/ir/converters/expressions/calls/call-site-analysis.d.ts +53 -0
- package/dist/ir/converters/expressions/calls/call-site-analysis.d.ts.map +1 -0
- package/dist/ir/converters/expressions/calls/call-site-analysis.js +554 -0
- package/dist/ir/converters/expressions/calls/call-site-analysis.js.map +1 -0
- package/dist/ir/converters/expressions/calls/new-converter.d.ts +21 -0
- package/dist/ir/converters/expressions/calls/new-converter.d.ts.map +1 -0
- package/dist/ir/converters/expressions/calls/new-converter.js +182 -0
- package/dist/ir/converters/expressions/calls/new-converter.js.map +1 -0
- package/dist/ir/converters/expressions/calls.d.ts +2 -28
- package/dist/ir/converters/expressions/calls.d.ts.map +1 -1
- package/dist/ir/converters/expressions/calls.js +2 -1344
- package/dist/ir/converters/expressions/calls.js.map +1 -1
- package/dist/ir/converters/expressions/collections.d.ts.map +1 -1
- package/dist/ir/converters/expressions/collections.js +37 -6
- package/dist/ir/converters/expressions/collections.js.map +1 -1
- package/dist/ir/converters/expressions/functions.js +1 -1
- package/dist/ir/converters/expressions/functions.js.map +1 -1
- package/dist/ir/converters/expressions/helpers.d.ts.map +1 -1
- package/dist/ir/converters/expressions/helpers.js +1 -0
- package/dist/ir/converters/expressions/helpers.js.map +1 -1
- package/dist/ir/converters/expressions/other.d.ts.map +1 -1
- package/dist/ir/converters/expressions/other.js +3 -2
- package/dist/ir/converters/expressions/other.js.map +1 -1
- package/dist/ir/converters/flow-narrowing.d.ts.map +1 -1
- package/dist/ir/converters/flow-narrowing.js +3 -2
- package/dist/ir/converters/flow-narrowing.js.map +1 -1
- package/dist/ir/converters/statements/declarations/classes/methods.js +1 -1
- package/dist/ir/converters/statements/declarations/classes/methods.js.map +1 -1
- package/dist/ir/converters/statements/declarations/type-aliases.js +1 -1
- package/dist/ir/converters/statements/declarations/type-aliases.js.map +1 -1
- package/dist/ir/converters/statements/declarations/variables.d.ts +2 -2
- package/dist/ir/converters/statements/declarations/variables.d.ts.map +1 -1
- package/dist/ir/converters/statements/declarations/variables.js +289 -2
- package/dist/ir/converters/statements/declarations/variables.js.map +1 -1
- package/dist/ir/expression-converter.d.ts +0 -1
- package/dist/ir/expression-converter.d.ts.map +1 -1
- package/dist/ir/expression-converter.js +0 -2
- package/dist/ir/expression-converter.js.map +1 -1
- package/dist/ir/generic-function-value-lowering.test.d.ts +2 -0
- package/dist/ir/generic-function-value-lowering.test.d.ts.map +1 -0
- package/dist/ir/generic-function-value-lowering.test.js +312 -0
- package/dist/ir/generic-function-value-lowering.test.js.map +1 -0
- package/dist/ir/generic-validator.d.ts +3 -4
- package/dist/ir/generic-validator.d.ts.map +1 -1
- package/dist/ir/generic-validator.js +3 -35
- package/dist/ir/generic-validator.js.map +1 -1
- package/dist/ir/program-context.d.ts +12 -0
- package/dist/ir/program-context.d.ts.map +1 -1
- package/dist/ir/program-context.js +2 -0
- package/dist/ir/program-context.js.map +1 -1
- package/dist/ir/statement-converter.d.ts +0 -2
- package/dist/ir/statement-converter.d.ts.map +1 -1
- package/dist/ir/statement-converter.js +0 -3
- package/dist/ir/statement-converter.js.map +1 -1
- package/dist/ir/type-system/internal/handle-types.d.ts +16 -16
- package/dist/ir/type-system/internal/handle-types.d.ts.map +1 -1
- package/dist/ir/type-system/internal/nominal-env.d.ts +0 -2
- package/dist/ir/type-system/internal/nominal-env.d.ts.map +1 -1
- package/dist/ir/type-system/internal/nominal-env.js +2 -6
- package/dist/ir/type-system/internal/nominal-env.js.map +1 -1
- package/dist/ir/type-system/internal/type-converter/converter.d.ts +3 -1
- package/dist/ir/type-system/internal/type-converter/converter.d.ts.map +1 -1
- package/dist/ir/type-system/internal/type-converter/converter.js +3 -1
- package/dist/ir/type-system/internal/type-converter/converter.js.map +1 -1
- package/dist/ir/type-system/internal/type-converter/objects.js +7 -1
- package/dist/ir/type-system/internal/type-converter/objects.js.map +1 -1
- package/dist/ir/type-system/internal/type-converter/orchestrator.d.ts +0 -2
- package/dist/ir/type-system/internal/type-converter/orchestrator.d.ts.map +1 -1
- package/dist/ir/type-system/internal/type-converter/orchestrator.js +322 -23
- package/dist/ir/type-system/internal/type-converter/orchestrator.js.map +1 -1
- package/dist/ir/type-system/internal/type-converter/orchestrator.test.d.ts +2 -0
- package/dist/ir/type-system/internal/type-converter/orchestrator.test.d.ts.map +1 -0
- package/dist/ir/type-system/internal/type-converter/orchestrator.test.js +265 -0
- package/dist/ir/type-system/internal/type-converter/orchestrator.test.js.map +1 -0
- package/dist/ir/type-system/internal/type-converter/primitives.d.ts.map +1 -1
- package/dist/ir/type-system/internal/type-converter/primitives.js +5 -0
- package/dist/ir/type-system/internal/type-converter/primitives.js.map +1 -1
- package/dist/ir/type-system/internal/type-converter/references.d.ts.map +1 -1
- package/dist/ir/type-system/internal/type-converter/references.js +67 -29
- package/dist/ir/type-system/internal/type-converter/references.js.map +1 -1
- package/dist/ir/type-system/internal/type-converter/utility-types.d.ts.map +1 -1
- package/dist/ir/type-system/internal/type-converter/utility-types.js +145 -0
- package/dist/ir/type-system/internal/type-converter/utility-types.js.map +1 -1
- package/dist/ir/type-system/internal/type-converter/utility-types.test.js +91 -1
- package/dist/ir/type-system/internal/type-converter/utility-types.test.js.map +1 -1
- package/dist/ir/type-system/internal/type-registry.d.ts +1 -1
- package/dist/ir/type-system/internal/type-registry.js +7 -7
- package/dist/ir/type-system/internal/type-registry.js.map +1 -1
- package/dist/ir/type-system/internal/universe/alias-table.d.ts +0 -14
- package/dist/ir/type-system/internal/universe/alias-table.d.ts.map +1 -1
- package/dist/ir/type-system/internal/universe/alias-table.js +0 -17
- package/dist/ir/type-system/internal/universe/alias-table.js.map +1 -1
- package/dist/ir/type-system/internal/universe/clr-catalog.d.ts +3 -0
- package/dist/ir/type-system/internal/universe/clr-catalog.d.ts.map +1 -1
- package/dist/ir/type-system/internal/universe/clr-catalog.js +4 -1044
- package/dist/ir/type-system/internal/universe/clr-catalog.js.map +1 -1
- package/dist/ir/type-system/internal/universe/clr-entry-converter.d.ts +51 -0
- package/dist/ir/type-system/internal/universe/clr-entry-converter.d.ts.map +1 -0
- package/dist/ir/type-system/internal/universe/clr-entry-converter.js +657 -0
- package/dist/ir/type-system/internal/universe/clr-entry-converter.js.map +1 -0
- package/dist/ir/type-system/internal/universe/clr-type-parser.d.ts +52 -0
- package/dist/ir/type-system/internal/universe/clr-type-parser.d.ts.map +1 -0
- package/dist/ir/type-system/internal/universe/clr-type-parser.js +481 -0
- package/dist/ir/type-system/internal/universe/clr-type-parser.js.map +1 -0
- package/dist/ir/type-system/internal/universe/clr-type-parser.test.d.ts +2 -0
- package/dist/ir/type-system/internal/universe/clr-type-parser.test.d.ts.map +1 -0
- package/dist/ir/type-system/internal/universe/clr-type-parser.test.js +55 -0
- package/dist/ir/type-system/internal/universe/clr-type-parser.test.js.map +1 -0
- package/dist/ir/type-system/internal/universe/index.d.ts +1 -1
- package/dist/ir/type-system/internal/universe/index.d.ts.map +1 -1
- package/dist/ir/type-system/internal/universe/index.js +1 -3
- package/dist/ir/type-system/internal/universe/index.js.map +1 -1
- package/dist/ir/type-system/internal/universe/unified-universe.test.js +2 -0
- package/dist/ir/type-system/internal/universe/unified-universe.test.js.map +1 -1
- package/dist/ir/type-system/type-system-call-resolution.d.ts +69 -0
- package/dist/ir/type-system/type-system-call-resolution.d.ts.map +1 -0
- package/dist/ir/type-system/type-system-call-resolution.js +1121 -0
- package/dist/ir/type-system/type-system-call-resolution.js.map +1 -0
- package/dist/ir/type-system/type-system-inference.d.ts +98 -0
- package/dist/ir/type-system/type-system-inference.d.ts.map +1 -0
- package/dist/ir/type-system/type-system-inference.js +1121 -0
- package/dist/ir/type-system/type-system-inference.js.map +1 -0
- package/dist/ir/type-system/type-system-relations.d.ts +15 -0
- package/dist/ir/type-system/type-system-relations.d.ts.map +1 -0
- package/dist/ir/type-system/type-system-relations.js +152 -0
- package/dist/ir/type-system/type-system-relations.js.map +1 -0
- package/dist/ir/type-system/type-system-state.d.ts +436 -0
- package/dist/ir/type-system/type-system-state.d.ts.map +1 -0
- package/dist/ir/type-system/type-system-state.js +212 -0
- package/dist/ir/type-system/type-system-state.js.map +1 -0
- package/dist/ir/type-system/type-system-utilities.d.ts +56 -0
- package/dist/ir/type-system/type-system-utilities.d.ts.map +1 -0
- package/dist/ir/type-system/type-system-utilities.js +373 -0
- package/dist/ir/type-system/type-system-utilities.js.map +1 -0
- package/dist/ir/type-system/type-system.d.ts +17 -358
- package/dist/ir/type-system/type-system.d.ts.map +1 -1
- package/dist/ir/type-system/type-system.js +67 -2945
- package/dist/ir/type-system/type-system.js.map +1 -1
- package/dist/ir/types/index.d.ts +1 -0
- package/dist/ir/types/index.d.ts.map +1 -1
- package/dist/ir/types/index.js +1 -0
- package/dist/ir/types/index.js.map +1 -1
- package/dist/ir/types/ir-substitution.js +1 -1
- package/dist/ir/types/ir-substitution.js.map +1 -1
- package/dist/ir/types/statements.d.ts +1 -1
- package/dist/ir/types/type-ops.d.ts +9 -0
- package/dist/ir/types/type-ops.d.ts.map +1 -0
- package/dist/ir/types/type-ops.js +134 -0
- package/dist/ir/types/type-ops.js.map +1 -0
- package/dist/ir/types/type-ops.test.d.ts +2 -0
- package/dist/ir/types/type-ops.test.d.ts.map +1 -0
- package/dist/ir/types/type-ops.test.js +73 -0
- package/dist/ir/types/type-ops.test.js.map +1 -0
- package/dist/ir/validation/anonymous-type-lowering-pass.d.ts.map +1 -1
- package/dist/ir/validation/anonymous-type-lowering-pass.js +34 -0
- package/dist/ir/validation/anonymous-type-lowering-pass.js.map +1 -1
- package/dist/ir/validation/anonymous-type-lowering-regressions.test.d.ts +2 -0
- package/dist/ir/validation/anonymous-type-lowering-regressions.test.d.ts.map +1 -0
- package/dist/ir/validation/anonymous-type-lowering-regressions.test.js +121 -0
- package/dist/ir/validation/anonymous-type-lowering-regressions.test.js.map +1 -0
- package/dist/ir/validation/attribute-collection/arg-extractor.d.ts +58 -0
- package/dist/ir/validation/attribute-collection/arg-extractor.d.ts.map +1 -0
- package/dist/ir/validation/attribute-collection/arg-extractor.js +284 -0
- package/dist/ir/validation/attribute-collection/arg-extractor.js.map +1 -0
- package/dist/ir/validation/attribute-collection/marker-parser.d.ts +28 -0
- package/dist/ir/validation/attribute-collection/marker-parser.d.ts.map +1 -0
- package/dist/ir/validation/attribute-collection/marker-parser.js +404 -0
- package/dist/ir/validation/attribute-collection/marker-parser.js.map +1 -0
- package/dist/ir/validation/attribute-collection/orchestrator.d.ts +28 -0
- package/dist/ir/validation/attribute-collection/orchestrator.d.ts.map +1 -0
- package/dist/ir/validation/attribute-collection/orchestrator.js +332 -0
- package/dist/ir/validation/attribute-collection/orchestrator.js.map +1 -0
- package/dist/ir/validation/attribute-collection-pass.d.ts +1 -23
- package/dist/ir/validation/attribute-collection-pass.d.ts.map +1 -1
- package/dist/ir/validation/attribute-collection-pass.js +1 -961
- package/dist/ir/validation/attribute-collection-pass.js.map +1 -1
- package/dist/ir/validation/attribute-collection-pass.test.js +12 -6
- package/dist/ir/validation/attribute-collection-pass.test.js.map +1 -1
- package/dist/ir/validation/numeric-invariants.test.js +29 -0
- package/dist/ir/validation/numeric-invariants.test.js.map +1 -1
- package/dist/ir/validation/numeric-proof-pass.d.ts.map +1 -1
- package/dist/ir/validation/numeric-proof-pass.js +21 -0
- package/dist/ir/validation/numeric-proof-pass.js.map +1 -1
- package/dist/ir/validation/soundness-gate.d.ts.map +1 -1
- package/dist/ir/validation/soundness-gate.js +2 -1
- package/dist/ir/validation/soundness-gate.js.map +1 -1
- package/dist/ir/validation/soundness-gate.test.js +69 -0
- package/dist/ir/validation/soundness-gate.test.js.map +1 -1
- package/dist/ir/validation/yield-lowering-pass.d.ts +11 -5
- package/dist/ir/validation/yield-lowering-pass.d.ts.map +1 -1
- package/dist/ir/validation/yield-lowering-pass.js +942 -48
- package/dist/ir/validation/yield-lowering-pass.js.map +1 -1
- package/dist/ir/validation/yield-lowering-pass.test.js +1333 -127
- package/dist/ir/validation/yield-lowering-pass.test.js.map +1 -1
- package/dist/program/binding-loader.d.ts +37 -0
- package/dist/program/binding-loader.d.ts.map +1 -0
- package/dist/program/binding-loader.js +155 -0
- package/dist/program/binding-loader.js.map +1 -0
- package/dist/program/binding-registry.d.ts +106 -0
- package/dist/program/binding-registry.d.ts.map +1 -0
- package/dist/program/binding-registry.js +590 -0
- package/dist/program/binding-registry.js.map +1 -0
- package/dist/program/binding-types.d.ts +166 -0
- package/dist/program/binding-types.d.ts.map +1 -0
- package/dist/program/binding-types.js +57 -0
- package/dist/program/binding-types.js.map +1 -0
- package/dist/program/bindings.d.ts +6 -271
- package/dist/program/bindings.d.ts.map +1 -1
- package/dist/program/bindings.js +7 -781
- package/dist/program/bindings.js.map +1 -1
- package/dist/program/creation.d.ts.map +1 -1
- package/dist/program/creation.js +104 -13
- package/dist/program/creation.js.map +1 -1
- package/dist/program/creation.test.js +133 -1
- package/dist/program/creation.test.js.map +1 -1
- package/dist/program/diagnostics.d.ts +1 -1
- package/dist/program/diagnostics.d.ts.map +1 -1
- package/dist/program/diagnostics.js +47 -2
- package/dist/program/diagnostics.js.map +1 -1
- package/dist/program/diagnostics.test.d.ts +2 -0
- package/dist/program/diagnostics.test.d.ts.map +1 -0
- package/dist/program/diagnostics.test.js +58 -0
- package/dist/program/diagnostics.test.js.map +1 -0
- package/dist/program/types.d.ts +2 -0
- package/dist/program/types.d.ts.map +1 -1
- package/dist/resolver/clr-bindings-resolver.d.ts +0 -1
- package/dist/resolver/clr-bindings-resolver.d.ts.map +1 -1
- package/dist/resolver/clr-bindings-resolver.js +22 -32
- package/dist/resolver/clr-bindings-resolver.js.map +1 -1
- package/dist/resolver/clr-bindings-resolver.test.js +0 -27
- package/dist/resolver/clr-bindings-resolver.test.js.map +1 -1
- package/dist/resolver/import-resolution.d.ts +3 -1
- package/dist/resolver/import-resolution.d.ts.map +1 -1
- package/dist/resolver/import-resolution.js +14 -11
- package/dist/resolver/import-resolution.js.map +1 -1
- package/dist/resolver/naming.d.ts.map +1 -1
- package/dist/resolver/naming.js +1 -0
- package/dist/resolver/naming.js.map +1 -1
- package/dist/resolver/node-module-aliases.d.ts +6 -0
- package/dist/resolver/node-module-aliases.d.ts.map +1 -0
- package/dist/resolver/node-module-aliases.js +164 -0
- package/dist/resolver/node-module-aliases.js.map +1 -0
- package/dist/resolver/node-module-aliases.test.d.ts +2 -0
- package/dist/resolver/node-module-aliases.test.d.ts.map +1 -0
- package/dist/resolver/node-module-aliases.test.js +64 -0
- package/dist/resolver/node-module-aliases.test.js.map +1 -0
- package/dist/resolver.test.js +103 -0
- package/dist/resolver.test.js.map +1 -1
- package/dist/surface/js-surface-shims.d.ts +3 -0
- package/dist/surface/js-surface-shims.d.ts.map +1 -0
- package/dist/surface/js-surface-shims.js +332 -0
- package/dist/surface/js-surface-shims.js.map +1 -0
- package/dist/surface/js-surface-shims.test.d.ts +2 -0
- package/dist/surface/js-surface-shims.test.d.ts.map +1 -0
- package/dist/surface/js-surface-shims.test.js +53 -0
- package/dist/surface/js-surface-shims.test.js.map +1 -0
- package/dist/surface/profiles.d.ts +10 -0
- package/dist/surface/profiles.d.ts.map +1 -0
- package/dist/surface/profiles.js +65 -0
- package/dist/surface/profiles.js.map +1 -0
- package/dist/surface/profiles.test.d.ts +2 -0
- package/dist/surface/profiles.test.d.ts.map +1 -0
- package/dist/surface/profiles.test.js +44 -0
- package/dist/surface/profiles.test.js.map +1 -0
- package/dist/types/diagnostic.d.ts +1 -1
- package/dist/types/diagnostic.d.ts.map +1 -1
- package/dist/types/diagnostic.js.map +1 -1
- package/dist/validation/features.d.ts.map +1 -1
- package/dist/validation/features.js +38 -13
- package/dist/validation/features.js.map +1 -1
- package/dist/validation/features.test.d.ts +2 -0
- package/dist/validation/features.test.d.ts.map +1 -0
- package/dist/validation/features.test.js +273 -0
- package/dist/validation/features.test.js.map +1 -0
- package/dist/validation/generics.d.ts +1 -1
- package/dist/validation/generics.d.ts.map +1 -1
- package/dist/validation/generics.js +2 -26
- package/dist/validation/generics.js.map +1 -1
- package/dist/validation/imports.d.ts.map +1 -1
- package/dist/validation/imports.js +29 -5
- package/dist/validation/imports.js.map +1 -1
- package/dist/validation/imports.test.d.ts +2 -0
- package/dist/validation/imports.test.d.ts.map +1 -0
- package/dist/validation/imports.test.js +211 -0
- package/dist/validation/imports.test.js.map +1 -0
- package/dist/validation/static-safety.d.ts +6 -6
- package/dist/validation/static-safety.d.ts.map +1 -1
- package/dist/validation/static-safety.js +163 -109
- package/dist/validation/static-safety.js.map +1 -1
- package/dist/validation/unsupported-utility-types.d.ts +3 -3
- package/dist/validation/unsupported-utility-types.d.ts.map +1 -1
- package/dist/validation/unsupported-utility-types.js +4 -7
- package/dist/validation/unsupported-utility-types.js.map +1 -1
- package/dist/validator.maximus.test.d.ts +2 -0
- package/dist/validator.maximus.test.d.ts.map +1 -0
- package/dist/validator.maximus.test.js +1214 -0
- package/dist/validator.maximus.test.js.map +1 -0
- package/dist/validator.test.js +152 -18
- package/dist/validator.test.js.map +1 -1
- package/package.json +1 -1
- package/dist/ir/converters/statements/declarations/registry.d.ts +0 -96
- package/dist/ir/converters/statements/declarations/registry.d.ts.map +0 -1
- package/dist/ir/converters/statements/declarations/registry.js +0 -130
- package/dist/ir/converters/statements/declarations/registry.js.map +0 -1
- package/dist/ir/this-parameter-inference.test.d.ts +0 -13
- package/dist/ir/this-parameter-inference.test.d.ts.map +0 -1
- package/dist/ir/this-parameter-inference.test.js +0 -165
- package/dist/ir/this-parameter-inference.test.js.map +0 -1
- package/dist/metadata/bindings-loader.d.ts +0 -41
- package/dist/metadata/bindings-loader.d.ts.map +0 -1
- package/dist/metadata/bindings-loader.js +0 -308
- package/dist/metadata/bindings-loader.js.map +0 -1
- package/dist/metadata/bindings-loader.test.d.ts +0 -5
- package/dist/metadata/bindings-loader.test.d.ts.map +0 -1
- package/dist/metadata/bindings-loader.test.js +0 -117
- package/dist/metadata/bindings-loader.test.js.map +0 -1
- package/dist/metadata/index.d.ts +0 -8
- package/dist/metadata/index.d.ts.map +0 -1
- package/dist/metadata/index.js +0 -7
- package/dist/metadata/index.js.map +0 -1
- package/dist/metadata/library-loader.d.ts +0 -42
- package/dist/metadata/library-loader.d.ts.map +0 -1
- package/dist/metadata/library-loader.js +0 -126
- package/dist/metadata/library-loader.js.map +0 -1
- package/dist/metadata/loader.d.ts +0 -26
- package/dist/metadata/loader.d.ts.map +0 -1
- package/dist/metadata/loader.js +0 -333
- package/dist/metadata/loader.js.map +0 -1
- package/dist/metadata/loader.test.d.ts +0 -5
- package/dist/metadata/loader.test.d.ts.map +0 -1
- package/dist/metadata/loader.test.js +0 -119
- package/dist/metadata/loader.test.js.map +0 -1
- package/dist/resolver/naming-policy.d.ts +0 -20
- package/dist/resolver/naming-policy.d.ts.map +0 -1
- package/dist/resolver/naming-policy.js +0 -40
- package/dist/resolver/naming-policy.js.map +0 -1
- package/dist/types/bindings.d.ts +0 -153
- package/dist/types/bindings.d.ts.map +0 -1
- package/dist/types/bindings.js +0 -14
- package/dist/types/bindings.js.map +0 -1
- package/dist/types/metadata.d.ts +0 -196
- package/dist/types/metadata.d.ts.map +0 -1
- package/dist/types/metadata.js +0 -10
- package/dist/types/metadata.js.map +0 -1
- package/dist/types/nested-types.d.ts +0 -111
- package/dist/types/nested-types.d.ts.map +0 -1
- package/dist/types/nested-types.js +0 -176
- package/dist/types/nested-types.js.map +0 -1
- package/dist/types/nested-types.test.d.ts +0 -5
- package/dist/types/nested-types.test.d.ts.map +0 -1
- package/dist/types/nested-types.test.js +0 -135
- package/dist/types/nested-types.test.js.map +0 -1
- package/dist/types/ref-parameters.d.ts +0 -123
- package/dist/types/ref-parameters.d.ts.map +0 -1
- package/dist/types/ref-parameters.js +0 -203
- package/dist/types/ref-parameters.js.map +0 -1
- package/dist/types/ref-parameters.test.d.ts +0 -5
- package/dist/types/ref-parameters.test.d.ts.map +0 -1
- package/dist/types/ref-parameters.test.js +0 -147
- package/dist/types/ref-parameters.test.js.map +0 -1
|
@@ -0,0 +1,1121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeSystem Inference — Expression Type Inference, Declaration/Member Queries,
|
|
3
|
+
* and Declaration Inspection Utilities
|
|
4
|
+
*
|
|
5
|
+
* Extracted from the monolithic type-system.ts. Contains:
|
|
6
|
+
* - Expression type inference (inferExpressionType, inferLambdaType)
|
|
7
|
+
* - Declaration type queries (typeOfDecl, typeOfMember, typeOfMemberId)
|
|
8
|
+
* - Initializer inference (tryInferTypeFromLiteralInitializer, tryInferTypeFromInitializer)
|
|
9
|
+
* - Call return type inference (tryInferReturnTypeFromCallExpression)
|
|
10
|
+
* - Declaration inspection utilities (hasTypeParameters, isTypeDecl, etc.)
|
|
11
|
+
*
|
|
12
|
+
* DAG position: depends on type-system-state, type-system-relations, type-system-call-resolution
|
|
13
|
+
*/
|
|
14
|
+
import * as ts from "typescript";
|
|
15
|
+
import { substituteIrType as irSubstitute, } from "../types/ir-substitution.js";
|
|
16
|
+
import { inferNumericKindFromRaw } from "../types/numeric-helpers.js";
|
|
17
|
+
import { getBinaryResultKind, TSONIC_TO_NUMERIC_KIND, } from "../types/numeric-kind.js";
|
|
18
|
+
import { unknownType, voidType } from "./types.js";
|
|
19
|
+
import { emitDiagnostic, normalizeToNominal, isNullishPrimitive, makeMemberCacheKey, stripNullishForInference, } from "./type-system-state.js";
|
|
20
|
+
import { typesEqual, containsTypeParameter } from "./type-system-relations.js";
|
|
21
|
+
import { convertTypeNode, lookupStructuralMember, resolveCall, delegateToFunctionType, } from "./type-system-call-resolution.js";
|
|
22
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
23
|
+
// typeOfDecl — Get declared type of a declaration
|
|
24
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
25
|
+
/**
|
|
26
|
+
* Derive IrType from NumericKind (deterministic, no TypeScript).
|
|
27
|
+
* Mirrors the logic in literals.ts deriveTypeFromNumericIntent.
|
|
28
|
+
*/
|
|
29
|
+
export const deriveTypeFromNumericKind = (kind) => {
|
|
30
|
+
if (kind === "Int32")
|
|
31
|
+
return { kind: "referenceType", name: "int" };
|
|
32
|
+
if (kind === "Int64")
|
|
33
|
+
return { kind: "referenceType", name: "long" };
|
|
34
|
+
if (kind === "Double")
|
|
35
|
+
return { kind: "primitiveType", name: "number" };
|
|
36
|
+
if (kind === "Single")
|
|
37
|
+
return { kind: "referenceType", name: "float" };
|
|
38
|
+
if (kind === "Byte")
|
|
39
|
+
return { kind: "referenceType", name: "byte" };
|
|
40
|
+
if (kind === "Int16")
|
|
41
|
+
return { kind: "referenceType", name: "short" };
|
|
42
|
+
if (kind === "UInt32")
|
|
43
|
+
return { kind: "referenceType", name: "uint" };
|
|
44
|
+
if (kind === "UInt64")
|
|
45
|
+
return { kind: "referenceType", name: "ulong" };
|
|
46
|
+
if (kind === "UInt16")
|
|
47
|
+
return { kind: "referenceType", name: "ushort" };
|
|
48
|
+
if (kind === "SByte")
|
|
49
|
+
return { kind: "referenceType", name: "sbyte" };
|
|
50
|
+
// Default to double for unknown
|
|
51
|
+
return { kind: "primitiveType", name: "number" };
|
|
52
|
+
};
|
|
53
|
+
export const unwrapParens = (expr) => {
|
|
54
|
+
let current = expr;
|
|
55
|
+
while (ts.isParenthesizedExpression(current)) {
|
|
56
|
+
current = current.expression;
|
|
57
|
+
}
|
|
58
|
+
return current;
|
|
59
|
+
};
|
|
60
|
+
export const isLambdaExpression = (expr) => {
|
|
61
|
+
const unwrapped = unwrapParens(expr);
|
|
62
|
+
return ts.isArrowFunction(unwrapped) || ts.isFunctionExpression(unwrapped);
|
|
63
|
+
};
|
|
64
|
+
export const getNumericKindFromIrType = (type) => {
|
|
65
|
+
if (type.kind === "primitiveType" && type.name === "number")
|
|
66
|
+
return "Double";
|
|
67
|
+
if (type.kind === "primitiveType") {
|
|
68
|
+
return TSONIC_TO_NUMERIC_KIND.get(type.name);
|
|
69
|
+
}
|
|
70
|
+
if (type.kind === "referenceType") {
|
|
71
|
+
return TSONIC_TO_NUMERIC_KIND.get(type.name);
|
|
72
|
+
}
|
|
73
|
+
return undefined;
|
|
74
|
+
};
|
|
75
|
+
export const unwrapAwaitedForInference = (type) => {
|
|
76
|
+
if (type.kind === "unionType") {
|
|
77
|
+
return {
|
|
78
|
+
kind: "unionType",
|
|
79
|
+
types: type.types.map((t) => (t ? unwrapAwaitedForInference(t) : t)),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
if (type.kind === "referenceType" &&
|
|
83
|
+
(type.name === "Promise" || type.name === "PromiseLike")) {
|
|
84
|
+
const inner = type.typeArguments?.[0];
|
|
85
|
+
if (inner)
|
|
86
|
+
return unwrapAwaitedForInference(inner);
|
|
87
|
+
}
|
|
88
|
+
if (type.kind === "referenceType") {
|
|
89
|
+
const clrName = type.typeId?.clrName;
|
|
90
|
+
if (clrName === "System.Threading.Tasks.Task" ||
|
|
91
|
+
clrName === "System.Threading.Tasks.ValueTask") {
|
|
92
|
+
return voidType;
|
|
93
|
+
}
|
|
94
|
+
if (clrName?.startsWith("System.Threading.Tasks.Task`") ||
|
|
95
|
+
clrName?.startsWith("System.Threading.Tasks.ValueTask`")) {
|
|
96
|
+
const inner = type.typeArguments?.[0];
|
|
97
|
+
if (inner)
|
|
98
|
+
return unwrapAwaitedForInference(inner);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return type;
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* Deterministically infer an expression's type using only:
|
|
105
|
+
* - local lambda parameter environment
|
|
106
|
+
* - declaration types (typeOfDecl)
|
|
107
|
+
* - numeric literal lexeme rules
|
|
108
|
+
*
|
|
109
|
+
* This is intentionally small: it's used only to type lambda bodies for
|
|
110
|
+
* initializer-driven generic inference (e.g., `Enumerable.select(..., x => x * 2)`).
|
|
111
|
+
*/
|
|
112
|
+
export const inferExpressionType = (state, expr, env) => {
|
|
113
|
+
const unwrapped = unwrapParens(expr);
|
|
114
|
+
if (ts.isAsExpression(unwrapped) || ts.isTypeAssertionExpression(unwrapped)) {
|
|
115
|
+
return convertTypeNode(state, unwrapped.type);
|
|
116
|
+
}
|
|
117
|
+
if (ts.isNonNullExpression(unwrapped)) {
|
|
118
|
+
const inner = inferExpressionType(state, unwrapped.expression, env);
|
|
119
|
+
if (!inner || inner.kind === "unknownType")
|
|
120
|
+
return undefined;
|
|
121
|
+
return stripNullishForInference(inner);
|
|
122
|
+
}
|
|
123
|
+
if (ts.isAwaitExpression(unwrapped)) {
|
|
124
|
+
const inner = inferExpressionType(state, unwrapped.expression, env);
|
|
125
|
+
if (!inner || inner.kind === "unknownType")
|
|
126
|
+
return undefined;
|
|
127
|
+
return unwrapAwaitedForInference(inner);
|
|
128
|
+
}
|
|
129
|
+
if (ts.isCallExpression(unwrapped)) {
|
|
130
|
+
return tryInferReturnTypeFromCallExpression(state, unwrapped, env);
|
|
131
|
+
}
|
|
132
|
+
if (ts.isNewExpression(unwrapped)) {
|
|
133
|
+
const sigId = state.resolveConstructorSignature(unwrapped);
|
|
134
|
+
if (!sigId)
|
|
135
|
+
return undefined;
|
|
136
|
+
const explicitTypeArgs = unwrapped.typeArguments && unwrapped.typeArguments.length > 0
|
|
137
|
+
? unwrapped.typeArguments.map((ta) => convertTypeNode(state, ta))
|
|
138
|
+
: undefined;
|
|
139
|
+
const argumentCount = unwrapped.arguments?.length ?? 0;
|
|
140
|
+
const argTypesWorking = Array(argumentCount).fill(undefined);
|
|
141
|
+
const args = unwrapped.arguments ?? [];
|
|
142
|
+
for (let i = 0; i < args.length; i++) {
|
|
143
|
+
const arg = args[i];
|
|
144
|
+
if (!arg)
|
|
145
|
+
continue;
|
|
146
|
+
if (ts.isSpreadElement(arg))
|
|
147
|
+
continue;
|
|
148
|
+
if (isLambdaExpression(arg))
|
|
149
|
+
continue;
|
|
150
|
+
const t = inferExpressionType(state, arg, env);
|
|
151
|
+
if (t && t.kind !== "unknownType") {
|
|
152
|
+
argTypesWorking[i] = t;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
const resolved = resolveCall(state, {
|
|
156
|
+
sigId,
|
|
157
|
+
argumentCount,
|
|
158
|
+
explicitTypeArgs,
|
|
159
|
+
argTypes: argTypesWorking,
|
|
160
|
+
});
|
|
161
|
+
return resolved.returnType.kind === "unknownType"
|
|
162
|
+
? undefined
|
|
163
|
+
: resolved.returnType;
|
|
164
|
+
}
|
|
165
|
+
if (ts.isPropertyAccessExpression(unwrapped)) {
|
|
166
|
+
const receiverType = inferExpressionType(state, unwrapped.expression, env);
|
|
167
|
+
if (!receiverType || receiverType.kind === "unknownType")
|
|
168
|
+
return undefined;
|
|
169
|
+
const memberType = typeOfMember(state, receiverType, {
|
|
170
|
+
kind: "byName",
|
|
171
|
+
name: unwrapped.name.text,
|
|
172
|
+
});
|
|
173
|
+
return memberType.kind === "unknownType" ? undefined : memberType;
|
|
174
|
+
}
|
|
175
|
+
if (ts.isElementAccessExpression(unwrapped)) {
|
|
176
|
+
const objectType = inferExpressionType(state, unwrapped.expression, env);
|
|
177
|
+
if (!objectType || objectType.kind === "unknownType")
|
|
178
|
+
return undefined;
|
|
179
|
+
if (objectType.kind === "arrayType") {
|
|
180
|
+
return objectType.elementType;
|
|
181
|
+
}
|
|
182
|
+
if (objectType.kind === "dictionaryType") {
|
|
183
|
+
return objectType.valueType;
|
|
184
|
+
}
|
|
185
|
+
if (objectType.kind === "primitiveType" && objectType.name === "string") {
|
|
186
|
+
return { kind: "primitiveType", name: "string" };
|
|
187
|
+
}
|
|
188
|
+
if (objectType.kind === "referenceType") {
|
|
189
|
+
return getIndexerInfo(state, objectType)?.valueType;
|
|
190
|
+
}
|
|
191
|
+
return undefined;
|
|
192
|
+
}
|
|
193
|
+
if (ts.isIdentifier(unwrapped)) {
|
|
194
|
+
const fromEnv = env.get(unwrapped.text);
|
|
195
|
+
if (fromEnv)
|
|
196
|
+
return fromEnv;
|
|
197
|
+
const declId = state.resolveIdentifier(unwrapped);
|
|
198
|
+
if (!declId)
|
|
199
|
+
return undefined;
|
|
200
|
+
const t = typeOfDecl(state, declId);
|
|
201
|
+
return t.kind === "unknownType" ? undefined : t;
|
|
202
|
+
}
|
|
203
|
+
if (ts.isNumericLiteral(unwrapped)) {
|
|
204
|
+
const numericKind = inferNumericKindFromRaw(unwrapped.getText());
|
|
205
|
+
return deriveTypeFromNumericKind(numericKind);
|
|
206
|
+
}
|
|
207
|
+
if (ts.isStringLiteral(unwrapped)) {
|
|
208
|
+
return { kind: "primitiveType", name: "string" };
|
|
209
|
+
}
|
|
210
|
+
if (ts.isNoSubstitutionTemplateLiteral(unwrapped) ||
|
|
211
|
+
ts.isTemplateExpression(unwrapped)) {
|
|
212
|
+
return { kind: "primitiveType", name: "string" };
|
|
213
|
+
}
|
|
214
|
+
if (unwrapped.kind === ts.SyntaxKind.TrueKeyword ||
|
|
215
|
+
unwrapped.kind === ts.SyntaxKind.FalseKeyword) {
|
|
216
|
+
return { kind: "primitiveType", name: "boolean" };
|
|
217
|
+
}
|
|
218
|
+
if (ts.isPrefixUnaryExpression(unwrapped)) {
|
|
219
|
+
if (unwrapped.operator === ts.SyntaxKind.ExclamationToken) {
|
|
220
|
+
return { kind: "primitiveType", name: "boolean" };
|
|
221
|
+
}
|
|
222
|
+
return inferExpressionType(state, unwrapped.operand, env);
|
|
223
|
+
}
|
|
224
|
+
if (ts.isBinaryExpression(unwrapped)) {
|
|
225
|
+
const op = unwrapped.operatorToken.kind;
|
|
226
|
+
// Comparisons / equality always return boolean.
|
|
227
|
+
if (op === ts.SyntaxKind.EqualsEqualsToken ||
|
|
228
|
+
op === ts.SyntaxKind.EqualsEqualsEqualsToken ||
|
|
229
|
+
op === ts.SyntaxKind.ExclamationEqualsToken ||
|
|
230
|
+
op === ts.SyntaxKind.ExclamationEqualsEqualsToken ||
|
|
231
|
+
op === ts.SyntaxKind.LessThanToken ||
|
|
232
|
+
op === ts.SyntaxKind.LessThanEqualsToken ||
|
|
233
|
+
op === ts.SyntaxKind.GreaterThanToken ||
|
|
234
|
+
op === ts.SyntaxKind.GreaterThanEqualsToken) {
|
|
235
|
+
return { kind: "primitiveType", name: "boolean" };
|
|
236
|
+
}
|
|
237
|
+
if (op === ts.SyntaxKind.AmpersandAmpersandToken ||
|
|
238
|
+
op === ts.SyntaxKind.BarBarToken) {
|
|
239
|
+
return { kind: "primitiveType", name: "boolean" };
|
|
240
|
+
}
|
|
241
|
+
if (op === ts.SyntaxKind.PlusToken ||
|
|
242
|
+
op === ts.SyntaxKind.MinusToken ||
|
|
243
|
+
op === ts.SyntaxKind.AsteriskToken ||
|
|
244
|
+
op === ts.SyntaxKind.SlashToken ||
|
|
245
|
+
op === ts.SyntaxKind.PercentToken) {
|
|
246
|
+
const leftType = inferExpressionType(state, unwrapped.left, env);
|
|
247
|
+
const rightType = inferExpressionType(state, unwrapped.right, env);
|
|
248
|
+
if (!leftType || !rightType)
|
|
249
|
+
return undefined;
|
|
250
|
+
// String concatenation
|
|
251
|
+
if (op === ts.SyntaxKind.PlusToken &&
|
|
252
|
+
((leftType.kind === "primitiveType" && leftType.name === "string") ||
|
|
253
|
+
(rightType.kind === "primitiveType" && rightType.name === "string"))) {
|
|
254
|
+
return { kind: "primitiveType", name: "string" };
|
|
255
|
+
}
|
|
256
|
+
const leftKind = getNumericKindFromIrType(leftType);
|
|
257
|
+
const rightKind = getNumericKindFromIrType(rightType);
|
|
258
|
+
if (!leftKind || !rightKind)
|
|
259
|
+
return undefined;
|
|
260
|
+
return deriveTypeFromNumericKind(getBinaryResultKind(leftKind, rightKind));
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return undefined;
|
|
264
|
+
};
|
|
265
|
+
export const inferLambdaType = (state, expr, expectedType) => {
|
|
266
|
+
const unwrapped = unwrapParens(expr);
|
|
267
|
+
if (!ts.isArrowFunction(unwrapped) && !ts.isFunctionExpression(unwrapped)) {
|
|
268
|
+
return undefined;
|
|
269
|
+
}
|
|
270
|
+
const expectedFnType = expectedType?.kind === "functionType"
|
|
271
|
+
? expectedType
|
|
272
|
+
: expectedType
|
|
273
|
+
? delegateToFunctionType(state, expectedType)
|
|
274
|
+
: undefined;
|
|
275
|
+
const parameters = unwrapped.parameters.map((p, index) => {
|
|
276
|
+
const name = ts.isIdentifier(p.name) ? p.name.text : `arg${index}`;
|
|
277
|
+
const paramType = p.type
|
|
278
|
+
? convertTypeNode(state, p.type)
|
|
279
|
+
: expectedFnType?.parameters[index]?.type;
|
|
280
|
+
return {
|
|
281
|
+
kind: "parameter",
|
|
282
|
+
pattern: {
|
|
283
|
+
kind: "identifierPattern",
|
|
284
|
+
name,
|
|
285
|
+
},
|
|
286
|
+
type: paramType,
|
|
287
|
+
initializer: undefined,
|
|
288
|
+
isOptional: !!p.questionToken,
|
|
289
|
+
isRest: !!p.dotDotDotToken,
|
|
290
|
+
passing: "value",
|
|
291
|
+
};
|
|
292
|
+
});
|
|
293
|
+
const env = new Map();
|
|
294
|
+
for (const p of parameters) {
|
|
295
|
+
if (p.pattern.kind === "identifierPattern" && p.pattern.name && p.type) {
|
|
296
|
+
env.set(p.pattern.name, p.type);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
const explicitReturnType = "type" in unwrapped && unwrapped.type
|
|
300
|
+
? convertTypeNode(state, unwrapped.type)
|
|
301
|
+
: undefined;
|
|
302
|
+
const expectedReturnType = expectedFnType?.returnType;
|
|
303
|
+
const inferredReturnType = explicitReturnType ??
|
|
304
|
+
(expectedReturnType && !containsTypeParameter(expectedReturnType)
|
|
305
|
+
? expectedReturnType
|
|
306
|
+
: undefined) ??
|
|
307
|
+
(() => {
|
|
308
|
+
if (ts.isBlock(unwrapped.body)) {
|
|
309
|
+
const returns = [];
|
|
310
|
+
const visit = (n) => {
|
|
311
|
+
if (ts.isFunctionLike(n) && n !== unwrapped)
|
|
312
|
+
return;
|
|
313
|
+
if (ts.isReturnStatement(n) && n.expression) {
|
|
314
|
+
returns.push(n.expression);
|
|
315
|
+
}
|
|
316
|
+
n.forEachChild(visit);
|
|
317
|
+
};
|
|
318
|
+
unwrapped.body.forEachChild(visit);
|
|
319
|
+
if (returns.length === 0)
|
|
320
|
+
return { kind: "voidType" };
|
|
321
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
322
|
+
const first = inferExpressionType(state, returns[0], env);
|
|
323
|
+
if (!first)
|
|
324
|
+
return undefined;
|
|
325
|
+
for (let i = 1; i < returns.length; i++) {
|
|
326
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
327
|
+
const t = inferExpressionType(state, returns[i], env);
|
|
328
|
+
if (!t || !typesEqual(t, first))
|
|
329
|
+
return undefined;
|
|
330
|
+
}
|
|
331
|
+
return first;
|
|
332
|
+
}
|
|
333
|
+
return inferExpressionType(state, unwrapped.body, env);
|
|
334
|
+
})();
|
|
335
|
+
if (!inferredReturnType)
|
|
336
|
+
return undefined;
|
|
337
|
+
return {
|
|
338
|
+
kind: "functionType",
|
|
339
|
+
parameters,
|
|
340
|
+
returnType: inferredReturnType,
|
|
341
|
+
};
|
|
342
|
+
};
|
|
343
|
+
/**
|
|
344
|
+
* Try to infer type from a variable declaration's literal initializer.
|
|
345
|
+
*
|
|
346
|
+
* DETERMINISM: Uses the raw lexeme form of the literal, not TS computed types.
|
|
347
|
+
* Only handles simple literal initializers:
|
|
348
|
+
* - Numeric literals → inferred via inferNumericKindFromRaw
|
|
349
|
+
* - String literals → primitiveType("string")
|
|
350
|
+
* - Boolean literals → primitiveType("boolean")
|
|
351
|
+
*
|
|
352
|
+
* Returns undefined if the initializer is not a simple literal.
|
|
353
|
+
*/
|
|
354
|
+
export const tryInferTypeFromLiteralInitializer = (_state, declNode) => {
|
|
355
|
+
// TypeScript's VariableDeclaration has an `initializer` property
|
|
356
|
+
const decl = declNode;
|
|
357
|
+
// Must have an initializer
|
|
358
|
+
if (!decl.initializer)
|
|
359
|
+
return undefined;
|
|
360
|
+
const init = decl.initializer;
|
|
361
|
+
if (init.kind === ts.SyntaxKind.NumericLiteral && init.getText) {
|
|
362
|
+
const raw = init.getText();
|
|
363
|
+
const numericKind = inferNumericKindFromRaw(raw);
|
|
364
|
+
return deriveTypeFromNumericKind(numericKind);
|
|
365
|
+
}
|
|
366
|
+
if (init.kind === ts.SyntaxKind.StringLiteral) {
|
|
367
|
+
return { kind: "primitiveType", name: "string" };
|
|
368
|
+
}
|
|
369
|
+
if (init.kind === ts.SyntaxKind.NoSubstitutionTemplateLiteral ||
|
|
370
|
+
init.kind === ts.SyntaxKind.TemplateExpression) {
|
|
371
|
+
return { kind: "primitiveType", name: "string" };
|
|
372
|
+
}
|
|
373
|
+
if (init.kind === ts.SyntaxKind.TrueKeyword ||
|
|
374
|
+
init.kind === ts.SyntaxKind.FalseKeyword) {
|
|
375
|
+
return { kind: "primitiveType", name: "boolean" };
|
|
376
|
+
}
|
|
377
|
+
// Not a simple literal - cannot infer
|
|
378
|
+
return undefined;
|
|
379
|
+
};
|
|
380
|
+
/**
|
|
381
|
+
* Try to infer type from a variable declaration's initializer using only
|
|
382
|
+
* deterministic sources (declarations + explicit syntax).
|
|
383
|
+
*
|
|
384
|
+
* Handles:
|
|
385
|
+
* - simple literals (delegates to tryInferTypeFromLiteralInitializer)
|
|
386
|
+
* - call expressions where the callee has an explicit declared return type
|
|
387
|
+
* - new expressions with explicit type arguments (or best-effort nominal type)
|
|
388
|
+
* - identifier initializers (propagate deterministically)
|
|
389
|
+
*/
|
|
390
|
+
export const tryInferReturnTypeFromCallExpression = (state, call, env) => {
|
|
391
|
+
const sigId = state.resolveCallSignature(call);
|
|
392
|
+
if (!sigId)
|
|
393
|
+
return undefined;
|
|
394
|
+
const explicitTypeArgs = call.typeArguments && call.typeArguments.length > 0
|
|
395
|
+
? call.typeArguments.map((ta) => convertTypeNode(state, ta))
|
|
396
|
+
: undefined;
|
|
397
|
+
const receiverType = (() => {
|
|
398
|
+
if (!ts.isPropertyAccessExpression(call.expression))
|
|
399
|
+
return undefined;
|
|
400
|
+
const receiverExpr = call.expression.expression;
|
|
401
|
+
const receiver = inferExpressionType(state, receiverExpr, env);
|
|
402
|
+
return receiver && receiver.kind !== "unknownType" ? receiver : undefined;
|
|
403
|
+
})();
|
|
404
|
+
const argumentCount = call.arguments.length;
|
|
405
|
+
// Two-pass: resolve once to get expected parameter types, then infer non-lambda args,
|
|
406
|
+
// then infer lambda arg types (from expected types + body), then final resolve.
|
|
407
|
+
const initialResolved = resolveCall(state, {
|
|
408
|
+
sigId,
|
|
409
|
+
argumentCount,
|
|
410
|
+
receiverType,
|
|
411
|
+
explicitTypeArgs,
|
|
412
|
+
});
|
|
413
|
+
const initialParameterTypes = initialResolved.parameterTypes;
|
|
414
|
+
const argTypesWorking = Array(argumentCount).fill(undefined);
|
|
415
|
+
for (let index = 0; index < call.arguments.length; index++) {
|
|
416
|
+
const arg = call.arguments[index];
|
|
417
|
+
if (!arg)
|
|
418
|
+
continue;
|
|
419
|
+
if (ts.isSpreadElement(arg))
|
|
420
|
+
continue;
|
|
421
|
+
if (isLambdaExpression(arg))
|
|
422
|
+
continue;
|
|
423
|
+
if (ts.isNumericLiteral(arg)) {
|
|
424
|
+
const numericKind = inferNumericKindFromRaw(arg.getText());
|
|
425
|
+
argTypesWorking[index] = deriveTypeFromNumericKind(numericKind);
|
|
426
|
+
continue;
|
|
427
|
+
}
|
|
428
|
+
if (ts.isStringLiteral(arg)) {
|
|
429
|
+
argTypesWorking[index] = { kind: "primitiveType", name: "string" };
|
|
430
|
+
continue;
|
|
431
|
+
}
|
|
432
|
+
if (arg.kind === ts.SyntaxKind.TrueKeyword ||
|
|
433
|
+
arg.kind === ts.SyntaxKind.FalseKeyword) {
|
|
434
|
+
argTypesWorking[index] = {
|
|
435
|
+
kind: "primitiveType",
|
|
436
|
+
name: "boolean",
|
|
437
|
+
};
|
|
438
|
+
continue;
|
|
439
|
+
}
|
|
440
|
+
if (ts.isIdentifier(arg)) {
|
|
441
|
+
const argDeclId = state.resolveIdentifier(arg);
|
|
442
|
+
if (!argDeclId)
|
|
443
|
+
continue;
|
|
444
|
+
const t = typeOfDecl(state, argDeclId);
|
|
445
|
+
if (t.kind !== "unknownType") {
|
|
446
|
+
argTypesWorking[index] = t;
|
|
447
|
+
}
|
|
448
|
+
continue;
|
|
449
|
+
}
|
|
450
|
+
if (ts.isCallExpression(arg)) {
|
|
451
|
+
const t = tryInferReturnTypeFromCallExpression(state, arg, env);
|
|
452
|
+
if (t) {
|
|
453
|
+
argTypesWorking[index] = t;
|
|
454
|
+
}
|
|
455
|
+
continue;
|
|
456
|
+
}
|
|
457
|
+
if (ts.isNewExpression(arg)) {
|
|
458
|
+
const nestedSigId = state.resolveConstructorSignature(arg);
|
|
459
|
+
if (!nestedSigId)
|
|
460
|
+
continue;
|
|
461
|
+
const nestedExplicitTypeArgs = arg.typeArguments && arg.typeArguments.length > 0
|
|
462
|
+
? arg.typeArguments.map((ta) => convertTypeNode(state, ta))
|
|
463
|
+
: undefined;
|
|
464
|
+
const nestedResolved = resolveCall(state, {
|
|
465
|
+
sigId: nestedSigId,
|
|
466
|
+
argumentCount: arg.arguments?.length ?? 0,
|
|
467
|
+
explicitTypeArgs: nestedExplicitTypeArgs,
|
|
468
|
+
});
|
|
469
|
+
if (nestedResolved.returnType.kind !== "unknownType") {
|
|
470
|
+
argTypesWorking[index] = nestedResolved.returnType;
|
|
471
|
+
}
|
|
472
|
+
continue;
|
|
473
|
+
}
|
|
474
|
+
// Fallback: infer from a small deterministic expression set (identifiers, literals,
|
|
475
|
+
// arithmetic, nested member/index access, calls, etc).
|
|
476
|
+
const t = inferExpressionType(state, arg, env);
|
|
477
|
+
if (t && t.kind !== "unknownType") {
|
|
478
|
+
argTypesWorking[index] = t;
|
|
479
|
+
continue;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
const lambdaContextResolved = resolveCall(state, {
|
|
483
|
+
sigId,
|
|
484
|
+
argumentCount,
|
|
485
|
+
receiverType,
|
|
486
|
+
explicitTypeArgs,
|
|
487
|
+
argTypes: argTypesWorking,
|
|
488
|
+
});
|
|
489
|
+
const parameterTypesForLambdaContext = lambdaContextResolved.parameterTypes ?? initialParameterTypes;
|
|
490
|
+
for (let index = 0; index < call.arguments.length; index++) {
|
|
491
|
+
const arg = call.arguments[index];
|
|
492
|
+
if (!arg)
|
|
493
|
+
continue;
|
|
494
|
+
if (ts.isSpreadElement(arg))
|
|
495
|
+
continue;
|
|
496
|
+
if (!isLambdaExpression(arg))
|
|
497
|
+
continue;
|
|
498
|
+
const expectedType = parameterTypesForLambdaContext[index];
|
|
499
|
+
const lambdaType = inferLambdaType(state, arg, expectedType);
|
|
500
|
+
if (lambdaType) {
|
|
501
|
+
argTypesWorking[index] = lambdaType;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
const finalResolved = resolveCall(state, {
|
|
505
|
+
sigId,
|
|
506
|
+
argumentCount,
|
|
507
|
+
receiverType,
|
|
508
|
+
explicitTypeArgs,
|
|
509
|
+
argTypes: argTypesWorking,
|
|
510
|
+
});
|
|
511
|
+
return finalResolved.returnType.kind === "unknownType"
|
|
512
|
+
? undefined
|
|
513
|
+
: finalResolved.returnType;
|
|
514
|
+
};
|
|
515
|
+
export const tryInferTypeFromInitializer = (state, declNode) => {
|
|
516
|
+
const literalType = tryInferTypeFromLiteralInitializer(state, declNode);
|
|
517
|
+
if (literalType)
|
|
518
|
+
return literalType;
|
|
519
|
+
if (!declNode || typeof declNode !== "object")
|
|
520
|
+
return undefined;
|
|
521
|
+
const node = declNode;
|
|
522
|
+
if (!ts.isVariableDeclaration(node))
|
|
523
|
+
return undefined;
|
|
524
|
+
let init = node.initializer;
|
|
525
|
+
if (!init)
|
|
526
|
+
return undefined;
|
|
527
|
+
while (ts.isParenthesizedExpression(init)) {
|
|
528
|
+
init = init.expression;
|
|
529
|
+
}
|
|
530
|
+
// Explicit type assertions are deterministic sources for variable typing.
|
|
531
|
+
// This supports patterns like:
|
|
532
|
+
// const xs = numbers as unknown as LinqSeq<int>;
|
|
533
|
+
// where the user intentionally supplies the type at the assertion site.
|
|
534
|
+
if (ts.isAsExpression(init) || ts.isTypeAssertionExpression(init)) {
|
|
535
|
+
return convertTypeNode(state, init.type);
|
|
536
|
+
}
|
|
537
|
+
if (ts.isNonNullExpression(init)) {
|
|
538
|
+
const inner = inferExpressionType(state, init.expression, new Map());
|
|
539
|
+
if (!inner || inner.kind === "unknownType")
|
|
540
|
+
return undefined;
|
|
541
|
+
return stripNullishForInference(inner);
|
|
542
|
+
}
|
|
543
|
+
if (ts.isAwaitExpression(init)) {
|
|
544
|
+
const inner = inferExpressionType(state, init.expression, new Map());
|
|
545
|
+
if (!inner || inner.kind === "unknownType")
|
|
546
|
+
return undefined;
|
|
547
|
+
return unwrapAwaitedForInference(inner);
|
|
548
|
+
}
|
|
549
|
+
if (ts.isCallExpression(init)) {
|
|
550
|
+
return tryInferReturnTypeFromCallExpression(state, init, new Map());
|
|
551
|
+
}
|
|
552
|
+
if (ts.isArrayLiteralExpression(init)) {
|
|
553
|
+
// Deterministic array literal typing for variable declarations:
|
|
554
|
+
// infer `T[]` only when all element types are deterministically known and equal.
|
|
555
|
+
const elementTypes = [];
|
|
556
|
+
const emptyEnv = new Map();
|
|
557
|
+
for (const el of init.elements) {
|
|
558
|
+
if (ts.isOmittedExpression(el)) {
|
|
559
|
+
return undefined;
|
|
560
|
+
}
|
|
561
|
+
if (ts.isSpreadElement(el)) {
|
|
562
|
+
return undefined;
|
|
563
|
+
}
|
|
564
|
+
const t = inferExpressionType(state, el, emptyEnv);
|
|
565
|
+
if (!t || t.kind === "unknownType") {
|
|
566
|
+
return undefined;
|
|
567
|
+
}
|
|
568
|
+
elementTypes.push(t);
|
|
569
|
+
}
|
|
570
|
+
if (elementTypes.length === 0)
|
|
571
|
+
return undefined;
|
|
572
|
+
const first = elementTypes[0];
|
|
573
|
+
if (first && elementTypes.every((t) => typesEqual(t, first))) {
|
|
574
|
+
return { kind: "arrayType", elementType: first };
|
|
575
|
+
}
|
|
576
|
+
return undefined;
|
|
577
|
+
}
|
|
578
|
+
// Phase 15: NewExpression branch - use constructor signature with argTypes
|
|
579
|
+
if (ts.isNewExpression(init)) {
|
|
580
|
+
const sigId = state.resolveConstructorSignature(init);
|
|
581
|
+
if (!sigId)
|
|
582
|
+
return undefined;
|
|
583
|
+
const explicitTypeArgs = init.typeArguments && init.typeArguments.length > 0
|
|
584
|
+
? init.typeArguments.map((ta) => convertTypeNode(state, ta))
|
|
585
|
+
: undefined;
|
|
586
|
+
// Derive argTypes conservatively from syntax (same pattern as CallExpression)
|
|
587
|
+
const args = init.arguments ?? [];
|
|
588
|
+
const argTypes = args.map((arg) => {
|
|
589
|
+
if (ts.isSpreadElement(arg))
|
|
590
|
+
return undefined;
|
|
591
|
+
if (ts.isNumericLiteral(arg)) {
|
|
592
|
+
const numericKind = inferNumericKindFromRaw(arg.getText());
|
|
593
|
+
return deriveTypeFromNumericKind(numericKind);
|
|
594
|
+
}
|
|
595
|
+
if (ts.isStringLiteral(arg)) {
|
|
596
|
+
return { kind: "primitiveType", name: "string" };
|
|
597
|
+
}
|
|
598
|
+
if (arg.kind === ts.SyntaxKind.TrueKeyword ||
|
|
599
|
+
arg.kind === ts.SyntaxKind.FalseKeyword) {
|
|
600
|
+
return { kind: "primitiveType", name: "boolean" };
|
|
601
|
+
}
|
|
602
|
+
if (ts.isIdentifier(arg)) {
|
|
603
|
+
const argDeclId = state.resolveIdentifier(arg);
|
|
604
|
+
if (!argDeclId)
|
|
605
|
+
return undefined;
|
|
606
|
+
const t = typeOfDecl(state, argDeclId);
|
|
607
|
+
return t.kind === "unknownType" ? undefined : t;
|
|
608
|
+
}
|
|
609
|
+
// Recursive handling for nested new expressions
|
|
610
|
+
if (ts.isNewExpression(arg)) {
|
|
611
|
+
const nestedSigId = state.resolveConstructorSignature(arg);
|
|
612
|
+
if (!nestedSigId)
|
|
613
|
+
return undefined;
|
|
614
|
+
const nestedExplicitTypeArgs = arg.typeArguments && arg.typeArguments.length > 0
|
|
615
|
+
? arg.typeArguments.map((ta) => convertTypeNode(state, ta))
|
|
616
|
+
: undefined;
|
|
617
|
+
const nestedResolved = resolveCall(state, {
|
|
618
|
+
sigId: nestedSigId,
|
|
619
|
+
argumentCount: arg.arguments?.length ?? 0,
|
|
620
|
+
explicitTypeArgs: nestedExplicitTypeArgs,
|
|
621
|
+
});
|
|
622
|
+
return nestedResolved.returnType.kind === "unknownType"
|
|
623
|
+
? undefined
|
|
624
|
+
: nestedResolved.returnType;
|
|
625
|
+
}
|
|
626
|
+
return undefined;
|
|
627
|
+
});
|
|
628
|
+
// Resolve constructor call with argTypes for inference
|
|
629
|
+
const resolved = resolveCall(state, {
|
|
630
|
+
sigId,
|
|
631
|
+
argumentCount: args.length,
|
|
632
|
+
explicitTypeArgs,
|
|
633
|
+
argTypes,
|
|
634
|
+
});
|
|
635
|
+
return resolved.returnType.kind === "unknownType"
|
|
636
|
+
? undefined
|
|
637
|
+
: resolved.returnType;
|
|
638
|
+
}
|
|
639
|
+
if (ts.isIdentifier(init)) {
|
|
640
|
+
const sourceDeclId = state.resolveIdentifier(init);
|
|
641
|
+
if (!sourceDeclId)
|
|
642
|
+
return undefined;
|
|
643
|
+
const sourceType = typeOfDecl(state, sourceDeclId);
|
|
644
|
+
return sourceType.kind === "unknownType" ? undefined : sourceType;
|
|
645
|
+
}
|
|
646
|
+
// Property access: const output = response.outputStream
|
|
647
|
+
// DETERMINISTIC: Infer via TypeSystem member lookup on a deterministically typed receiver.
|
|
648
|
+
if (ts.isPropertyAccessExpression(init)) {
|
|
649
|
+
const receiverType = inferExpressionType(state, init.expression, new Map());
|
|
650
|
+
if (!receiverType || receiverType.kind === "unknownType")
|
|
651
|
+
return undefined;
|
|
652
|
+
const memberType = typeOfMember(state, receiverType, {
|
|
653
|
+
kind: "byName",
|
|
654
|
+
name: init.name.text,
|
|
655
|
+
});
|
|
656
|
+
return memberType.kind === "unknownType" ? undefined : memberType;
|
|
657
|
+
}
|
|
658
|
+
// Element access: const first = items[0]
|
|
659
|
+
// DETERMINISTIC: Infer element type from a deterministically typed receiver.
|
|
660
|
+
if (ts.isElementAccessExpression(init)) {
|
|
661
|
+
const inferred = inferExpressionType(state, init, new Map());
|
|
662
|
+
return inferred && inferred.kind !== "unknownType" ? inferred : undefined;
|
|
663
|
+
}
|
|
664
|
+
const inferred = inferExpressionType(state, init, new Map());
|
|
665
|
+
if (inferred && inferred.kind !== "unknownType") {
|
|
666
|
+
return inferred;
|
|
667
|
+
}
|
|
668
|
+
return undefined;
|
|
669
|
+
};
|
|
670
|
+
export const typeOfDecl = (state, declId) => {
|
|
671
|
+
// Check cache first
|
|
672
|
+
const cached = state.declTypeCache.get(declId.id);
|
|
673
|
+
if (cached)
|
|
674
|
+
return cached;
|
|
675
|
+
const declInfo = state.handleRegistry.getDecl(declId);
|
|
676
|
+
if (!declInfo) {
|
|
677
|
+
emitDiagnostic(state, "TSN5203", "Cannot resolve declaration");
|
|
678
|
+
const result = unknownType;
|
|
679
|
+
state.declTypeCache.set(declId.id, result);
|
|
680
|
+
return result;
|
|
681
|
+
}
|
|
682
|
+
let result;
|
|
683
|
+
if (declInfo.typeNode) {
|
|
684
|
+
// Explicit type annotation - convert to IR
|
|
685
|
+
result = convertTypeNode(state, declInfo.typeNode);
|
|
686
|
+
}
|
|
687
|
+
else if (declInfo.kind === "class" ||
|
|
688
|
+
declInfo.kind === "interface" ||
|
|
689
|
+
declInfo.kind === "enum") {
|
|
690
|
+
// Class/interface/enum - return reference type
|
|
691
|
+
result = {
|
|
692
|
+
kind: "referenceType",
|
|
693
|
+
name: declInfo.fqName ?? "unknown",
|
|
694
|
+
};
|
|
695
|
+
}
|
|
696
|
+
else if (declInfo.kind === "function") {
|
|
697
|
+
// Function without type annotation - need to build function type from signature
|
|
698
|
+
// For now, return unknownType as we need the signature ID
|
|
699
|
+
emitDiagnostic(state, "TSN5201", `Function '${declInfo.fqName ?? "unknown"}' requires explicit return type`);
|
|
700
|
+
result = unknownType;
|
|
701
|
+
}
|
|
702
|
+
else if (declInfo.kind === "variable" && declInfo.declNode) {
|
|
703
|
+
// Variable without type annotation - infer from deterministic initializer
|
|
704
|
+
const inferred = tryInferTypeFromInitializer(state, declInfo.declNode);
|
|
705
|
+
if (inferred) {
|
|
706
|
+
result = inferred;
|
|
707
|
+
}
|
|
708
|
+
else {
|
|
709
|
+
// Not a simple literal - require explicit type annotation
|
|
710
|
+
emitDiagnostic(state, "TSN5201", `Declaration requires explicit type annotation`);
|
|
711
|
+
result = unknownType;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
else {
|
|
715
|
+
// Parameter or other declaration without type annotation
|
|
716
|
+
emitDiagnostic(state, "TSN5201", `Declaration requires explicit type annotation`);
|
|
717
|
+
result = unknownType;
|
|
718
|
+
}
|
|
719
|
+
state.declTypeCache.set(declId.id, result);
|
|
720
|
+
return result;
|
|
721
|
+
};
|
|
722
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
723
|
+
// typeOfMember — Get declared type of a member (with inheritance substitution)
|
|
724
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
725
|
+
export const typeOfMember = (state, receiver, member, site) => {
|
|
726
|
+
const memberName = member.kind === "byName" ? member.name : "unknown"; // MemberId.name not defined yet
|
|
727
|
+
// Common nullish unions (T | undefined | null) should behave like T for member lookup.
|
|
728
|
+
// This preserves deterministic typing for patterns like:
|
|
729
|
+
// const url = request.url; if (!url) return; url.absolutePath
|
|
730
|
+
const effectiveReceiver = receiver.kind === "unionType"
|
|
731
|
+
? (() => {
|
|
732
|
+
const nonNullish = receiver.types.filter((t) => t && !isNullishPrimitive(t));
|
|
733
|
+
return nonNullish.length === 1 && nonNullish[0]
|
|
734
|
+
? nonNullish[0]
|
|
735
|
+
: receiver;
|
|
736
|
+
})()
|
|
737
|
+
: receiver;
|
|
738
|
+
// Built-in dictionary pseudo-members used by TS-side ergonomics.
|
|
739
|
+
// Record<K, V> lowers to dictionaryType, and callers often use:
|
|
740
|
+
// - dict.Keys[i]
|
|
741
|
+
// - dict.Values[i]
|
|
742
|
+
// - dict.Count / dict.Length
|
|
743
|
+
//
|
|
744
|
+
// Resolve these deterministically at TypeSystem level so downstream passes
|
|
745
|
+
// (numeric proof, element access typing) don't receive unknownType poison.
|
|
746
|
+
if (effectiveReceiver.kind === "dictionaryType") {
|
|
747
|
+
if (memberName === "Keys") {
|
|
748
|
+
return {
|
|
749
|
+
kind: "arrayType",
|
|
750
|
+
elementType: effectiveReceiver.keyType,
|
|
751
|
+
};
|
|
752
|
+
}
|
|
753
|
+
if (memberName === "Values") {
|
|
754
|
+
return {
|
|
755
|
+
kind: "arrayType",
|
|
756
|
+
elementType: effectiveReceiver.valueType,
|
|
757
|
+
};
|
|
758
|
+
}
|
|
759
|
+
if (memberName === "Count" || memberName === "Length") {
|
|
760
|
+
return { kind: "primitiveType", name: "int" };
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
// Built-in array pseudo-members.
|
|
764
|
+
// Arrays are structural IR types and may not resolve via nominal lookup.
|
|
765
|
+
if (effectiveReceiver.kind === "arrayType") {
|
|
766
|
+
if (memberName === "Length" || memberName === "Count") {
|
|
767
|
+
return { kind: "primitiveType", name: "int" };
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
// Tuples behave like fixed-size arrays for length access.
|
|
771
|
+
if (effectiveReceiver.kind === "tupleType") {
|
|
772
|
+
if (memberName === "Length" || memberName === "Count") {
|
|
773
|
+
return { kind: "primitiveType", name: "int" };
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
// 1. Normalize receiver to nominal form
|
|
777
|
+
const normalized = normalizeToNominal(state, effectiveReceiver);
|
|
778
|
+
if (!normalized) {
|
|
779
|
+
// Handle structural types (objectType)
|
|
780
|
+
if (effectiveReceiver.kind === "objectType" ||
|
|
781
|
+
(effectiveReceiver.kind === "referenceType" &&
|
|
782
|
+
effectiveReceiver.structuralMembers)) {
|
|
783
|
+
return lookupStructuralMember(state, effectiveReceiver, memberName, site);
|
|
784
|
+
}
|
|
785
|
+
emitDiagnostic(state, "TSN5203", `Cannot resolve member '${memberName}' on type`, site);
|
|
786
|
+
return unknownType;
|
|
787
|
+
}
|
|
788
|
+
// 2. Check cache
|
|
789
|
+
const cacheKey = makeMemberCacheKey(normalized.typeId.stableId, memberName, normalized.typeArgs);
|
|
790
|
+
const cached = state.memberDeclaredTypeCache.get(cacheKey);
|
|
791
|
+
if (cached)
|
|
792
|
+
return cached;
|
|
793
|
+
// 3. Use NominalEnv to find declaring type + substitution (Phase 6: TypeId-based)
|
|
794
|
+
const lookupResult = state.nominalEnv.findMemberDeclaringType(normalized.typeId, normalized.typeArgs, memberName);
|
|
795
|
+
// 4a. If NominalEnv found the member, get its declared type from Universe
|
|
796
|
+
if (lookupResult) {
|
|
797
|
+
const memberEntry = state.unifiedCatalog.getMember(lookupResult.declaringTypeId, memberName);
|
|
798
|
+
// Property/field member: return its declared type.
|
|
799
|
+
const memberType = memberEntry?.type;
|
|
800
|
+
if (memberType) {
|
|
801
|
+
const result = irSubstitute(memberType, lookupResult.substitution);
|
|
802
|
+
state.memberDeclaredTypeCache.set(cacheKey, result);
|
|
803
|
+
return result;
|
|
804
|
+
}
|
|
805
|
+
// Method member: materialize a callable function type from the first signature.
|
|
806
|
+
// Call resolution (resolveCall) uses SignatureId for overload selection; this
|
|
807
|
+
// type is used only to keep member access expressions deterministic.
|
|
808
|
+
const firstSig = memberEntry?.signatures?.[0];
|
|
809
|
+
if (firstSig) {
|
|
810
|
+
const funcType = {
|
|
811
|
+
kind: "functionType",
|
|
812
|
+
parameters: firstSig.parameters.map((p) => ({
|
|
813
|
+
kind: "parameter",
|
|
814
|
+
pattern: {
|
|
815
|
+
kind: "identifierPattern",
|
|
816
|
+
name: p.name,
|
|
817
|
+
},
|
|
818
|
+
type: p.type,
|
|
819
|
+
initializer: undefined,
|
|
820
|
+
isOptional: p.isOptional,
|
|
821
|
+
isRest: p.isRest,
|
|
822
|
+
passing: p.mode,
|
|
823
|
+
})),
|
|
824
|
+
returnType: firstSig.returnType,
|
|
825
|
+
};
|
|
826
|
+
const result = irSubstitute(funcType, lookupResult.substitution);
|
|
827
|
+
state.memberDeclaredTypeCache.set(cacheKey, result);
|
|
828
|
+
return result;
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
// 5. Member not found anywhere
|
|
832
|
+
emitDiagnostic(state, "TSN5203", `Member '${memberName}' not found`, site);
|
|
833
|
+
return unknownType;
|
|
834
|
+
};
|
|
835
|
+
export const parseIndexerKeyClrType = (stableId) => {
|
|
836
|
+
const memberSep = stableId.indexOf("::");
|
|
837
|
+
if (memberSep < 0)
|
|
838
|
+
return undefined;
|
|
839
|
+
const bracketStart = stableId.indexOf("[", memberSep);
|
|
840
|
+
if (bracketStart < 0)
|
|
841
|
+
return undefined;
|
|
842
|
+
let depth = 0;
|
|
843
|
+
let bracketEnd = -1;
|
|
844
|
+
for (let i = bracketStart; i < stableId.length; i++) {
|
|
845
|
+
const ch = stableId[i];
|
|
846
|
+
if (ch === "[")
|
|
847
|
+
depth++;
|
|
848
|
+
if (ch === "]") {
|
|
849
|
+
depth--;
|
|
850
|
+
if (depth === 0) {
|
|
851
|
+
bracketEnd = i;
|
|
852
|
+
break;
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
if (bracketEnd < 0)
|
|
857
|
+
return undefined;
|
|
858
|
+
const rawParams = stableId.slice(bracketStart + 1, bracketEnd);
|
|
859
|
+
// Split on top-level commas to support nested generic types.
|
|
860
|
+
const splitTopLevel = (value) => {
|
|
861
|
+
const parts = [];
|
|
862
|
+
let start = 0;
|
|
863
|
+
let bracketDepth = 0;
|
|
864
|
+
for (let i = 0; i < value.length; i++) {
|
|
865
|
+
const c = value[i];
|
|
866
|
+
if (c === "[")
|
|
867
|
+
bracketDepth++;
|
|
868
|
+
else if (c === "]" && bracketDepth > 0)
|
|
869
|
+
bracketDepth--;
|
|
870
|
+
else if (c === "," && bracketDepth === 0) {
|
|
871
|
+
parts.push(value.slice(start, i).trim());
|
|
872
|
+
start = i + 1;
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
parts.push(value.slice(start).trim());
|
|
876
|
+
return parts.filter((p) => p.length > 0);
|
|
877
|
+
};
|
|
878
|
+
const params = splitTopLevel(rawParams);
|
|
879
|
+
if (params.length !== 1)
|
|
880
|
+
return undefined;
|
|
881
|
+
const first = params[0];
|
|
882
|
+
if (!first)
|
|
883
|
+
return undefined;
|
|
884
|
+
// Strip assembly qualification (", Assembly, Version=..., ...") if present.
|
|
885
|
+
const withoutAsm = first.includes(",")
|
|
886
|
+
? (first.split(",")[0] ?? first)
|
|
887
|
+
: first;
|
|
888
|
+
return withoutAsm.trim();
|
|
889
|
+
};
|
|
890
|
+
export const getIndexerInfo = (state, receiver, _site) => {
|
|
891
|
+
const normalized = normalizeToNominal(state, receiver);
|
|
892
|
+
if (!normalized)
|
|
893
|
+
return undefined;
|
|
894
|
+
// Walk inheritance chain to find the first indexer property.
|
|
895
|
+
const chain = state.nominalEnv.getInheritanceChain(normalized.typeId);
|
|
896
|
+
for (const typeId of chain) {
|
|
897
|
+
const members = state.unifiedCatalog.getMembers(typeId);
|
|
898
|
+
const indexers = Array.from(members.values()).filter((m) => m.memberKind === "property" && m.isIndexer);
|
|
899
|
+
if (indexers.length === 0)
|
|
900
|
+
continue;
|
|
901
|
+
if (indexers.length > 1)
|
|
902
|
+
return undefined;
|
|
903
|
+
const indexer = indexers[0];
|
|
904
|
+
if (!indexer?.type)
|
|
905
|
+
return undefined;
|
|
906
|
+
const keyClrType = parseIndexerKeyClrType(indexer.stableId);
|
|
907
|
+
if (!keyClrType)
|
|
908
|
+
return undefined;
|
|
909
|
+
const inst = state.nominalEnv.getInstantiation(normalized.typeId, normalized.typeArgs, typeId);
|
|
910
|
+
const valueType = inst && inst.size > 0
|
|
911
|
+
? irSubstitute(indexer.type, inst)
|
|
912
|
+
: indexer.type;
|
|
913
|
+
return { keyClrType, valueType };
|
|
914
|
+
}
|
|
915
|
+
return undefined;
|
|
916
|
+
};
|
|
917
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
918
|
+
// hasTypeParameters — Check if declaration has type parameters
|
|
919
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
920
|
+
export const hasTypeParameters = (state, declId) => {
|
|
921
|
+
const declInfo = state.handleRegistry.getDecl(declId);
|
|
922
|
+
if (!declInfo?.declNode)
|
|
923
|
+
return false;
|
|
924
|
+
// Check the declaration node for type parameters
|
|
925
|
+
// We need to import ts to check for type parameter declarations
|
|
926
|
+
// Access the declNode as any to check for typeParameters property
|
|
927
|
+
const declNode = declInfo.declNode;
|
|
928
|
+
return !!(declNode.typeParameters && declNode.typeParameters.length > 0);
|
|
929
|
+
};
|
|
930
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
931
|
+
// typeOfMemberId — Get type of member by handle
|
|
932
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
933
|
+
export const typeOfMemberId = (state, memberId) => {
|
|
934
|
+
const memberInfo = state.handleRegistry.getMember(memberId);
|
|
935
|
+
if (!memberInfo) {
|
|
936
|
+
return unknownType;
|
|
937
|
+
}
|
|
938
|
+
// If the member has a type node, convert it
|
|
939
|
+
if (memberInfo.typeNode) {
|
|
940
|
+
return convertTypeNode(state, memberInfo.typeNode);
|
|
941
|
+
}
|
|
942
|
+
// Otherwise, attempt to recover type deterministically from the member declaration.
|
|
943
|
+
// This is required for namespace imports (`import * as X`) where members are
|
|
944
|
+
// function declarations / const declarations (no typeNode captured by Binding).
|
|
945
|
+
const decl = memberInfo.declNode;
|
|
946
|
+
if (decl) {
|
|
947
|
+
if (ts.isFunctionDeclaration(decl)) {
|
|
948
|
+
// Determinism: require explicit parameter + return annotations.
|
|
949
|
+
if (!decl.type)
|
|
950
|
+
return unknownType;
|
|
951
|
+
if (decl.parameters.some((p) => p.type === undefined))
|
|
952
|
+
return unknownType;
|
|
953
|
+
const parameters = decl.parameters.map((p) => ({
|
|
954
|
+
kind: "parameter",
|
|
955
|
+
pattern: {
|
|
956
|
+
kind: "identifierPattern",
|
|
957
|
+
name: ts.isIdentifier(p.name) ? p.name.text : "param",
|
|
958
|
+
},
|
|
959
|
+
type: p.type ? convertTypeNode(state, p.type) : undefined,
|
|
960
|
+
initializer: undefined,
|
|
961
|
+
isOptional: !!p.questionToken || !!p.initializer,
|
|
962
|
+
isRest: !!p.dotDotDotToken,
|
|
963
|
+
passing: "value",
|
|
964
|
+
}));
|
|
965
|
+
const returnType = convertTypeNode(state, decl.type);
|
|
966
|
+
const fnType = {
|
|
967
|
+
kind: "functionType",
|
|
968
|
+
parameters,
|
|
969
|
+
returnType,
|
|
970
|
+
};
|
|
971
|
+
return fnType;
|
|
972
|
+
}
|
|
973
|
+
if (ts.isVariableDeclaration(decl)) {
|
|
974
|
+
if (decl.type)
|
|
975
|
+
return convertTypeNode(state, decl.type);
|
|
976
|
+
const inferred = tryInferTypeFromInitializer(state, decl);
|
|
977
|
+
return inferred ?? unknownType;
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
return unknownType;
|
|
981
|
+
};
|
|
982
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
983
|
+
// getFQNameOfDecl — Get fully-qualified name of declaration
|
|
984
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
985
|
+
export const getFQNameOfDecl = (state, declId) => {
|
|
986
|
+
const declInfo = state.handleRegistry.getDecl(declId);
|
|
987
|
+
return declInfo?.fqName;
|
|
988
|
+
};
|
|
989
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
990
|
+
// isTypeDecl — Check if declaration is a type
|
|
991
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
992
|
+
export const isTypeDecl = (state, declId) => {
|
|
993
|
+
const declInfo = state.handleRegistry.getDecl(declId);
|
|
994
|
+
if (!declInfo)
|
|
995
|
+
return false;
|
|
996
|
+
const typeKinds = [
|
|
997
|
+
"interface",
|
|
998
|
+
"class",
|
|
999
|
+
"typeAlias",
|
|
1000
|
+
"enum",
|
|
1001
|
+
];
|
|
1002
|
+
return typeKinds.includes(declInfo.kind);
|
|
1003
|
+
};
|
|
1004
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
1005
|
+
// isInterfaceDecl — Check if declaration is an interface
|
|
1006
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
1007
|
+
export const isInterfaceDecl = (state, declId) => {
|
|
1008
|
+
const declInfo = state.handleRegistry.getDecl(declId);
|
|
1009
|
+
return declInfo?.kind === "interface";
|
|
1010
|
+
};
|
|
1011
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
1012
|
+
// isTypeAliasToObjectLiteral — Check if type alias points to object literal
|
|
1013
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
1014
|
+
export const isTypeAliasToObjectLiteral = (state, declId) => {
|
|
1015
|
+
const declInfo = state.handleRegistry.getDecl(declId);
|
|
1016
|
+
if (!declInfo || declInfo.kind !== "typeAlias")
|
|
1017
|
+
return false;
|
|
1018
|
+
// Check if the typeNode is a type literal node
|
|
1019
|
+
// We need to access the declNode to get the type alias declaration
|
|
1020
|
+
const declNode = declInfo.declNode;
|
|
1021
|
+
if (!declNode?.type)
|
|
1022
|
+
return false;
|
|
1023
|
+
return declNode.type.kind === ts.SyntaxKind.TypeLiteral;
|
|
1024
|
+
};
|
|
1025
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
1026
|
+
// signatureHasConditionalReturn — Check for conditional return type
|
|
1027
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
1028
|
+
export const signatureHasConditionalReturn = (state, sigId) => {
|
|
1029
|
+
const sigInfo = state.handleRegistry.getSignature(sigId);
|
|
1030
|
+
if (!sigInfo)
|
|
1031
|
+
return false;
|
|
1032
|
+
const returnTypeNode = sigInfo.returnTypeNode;
|
|
1033
|
+
if (!returnTypeNode)
|
|
1034
|
+
return false;
|
|
1035
|
+
return returnTypeNode.kind === ts.SyntaxKind.ConditionalType;
|
|
1036
|
+
};
|
|
1037
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
1038
|
+
// signatureHasVariadicTypeParams — Check for variadic type parameters
|
|
1039
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
1040
|
+
export const signatureHasVariadicTypeParams = (state, sigId) => {
|
|
1041
|
+
const sigInfo = state.handleRegistry.getSignature(sigId);
|
|
1042
|
+
if (!sigInfo)
|
|
1043
|
+
return false;
|
|
1044
|
+
if (!sigInfo.typeParameters)
|
|
1045
|
+
return false;
|
|
1046
|
+
for (const typeParam of sigInfo.typeParameters) {
|
|
1047
|
+
const constraintNode = typeParam.constraintNode;
|
|
1048
|
+
if (!constraintNode)
|
|
1049
|
+
continue;
|
|
1050
|
+
// Check if constraint is an array type (variadic pattern: T extends unknown[])
|
|
1051
|
+
if (constraintNode.kind === ts.SyntaxKind.ArrayType) {
|
|
1052
|
+
const elementType = constraintNode.elementType;
|
|
1053
|
+
if (!elementType)
|
|
1054
|
+
continue;
|
|
1055
|
+
// Check for unknown[] or any[] constraint
|
|
1056
|
+
if (elementType.kind === ts.SyntaxKind.UnknownKeyword ||
|
|
1057
|
+
elementType.kind === ts.SyntaxKind.AnyKeyword) {
|
|
1058
|
+
return true;
|
|
1059
|
+
}
|
|
1060
|
+
// Also check for type reference to "unknown" or "any"
|
|
1061
|
+
const typeName = elementType.typeName?.text;
|
|
1062
|
+
if (typeName === "unknown" || typeName === "any") {
|
|
1063
|
+
return true;
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
return false;
|
|
1068
|
+
};
|
|
1069
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
1070
|
+
// declHasTypeAnnotation — Check if declaration has explicit type
|
|
1071
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
1072
|
+
export const declHasTypeAnnotation = (state, declId) => {
|
|
1073
|
+
const declInfo = state.handleRegistry.getDecl(declId);
|
|
1074
|
+
return declInfo?.typeNode !== undefined;
|
|
1075
|
+
};
|
|
1076
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
1077
|
+
// checkTsClassMemberOverride — Check if member can be overridden
|
|
1078
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
1079
|
+
/**
|
|
1080
|
+
* Check if a class member overrides a base class member.
|
|
1081
|
+
*
|
|
1082
|
+
* ALICE'S SPEC: Uses captured ClassMemberNames (pure data) from Binding.
|
|
1083
|
+
* No TS AST inspection, no SyntaxKind numbers. TS-version safe.
|
|
1084
|
+
*/
|
|
1085
|
+
export const checkTsClassMemberOverride = (state, declId, memberName, memberKind) => {
|
|
1086
|
+
const declInfo = state.handleRegistry.getDecl(declId);
|
|
1087
|
+
const members = declInfo?.classMemberNames;
|
|
1088
|
+
// No class member info available
|
|
1089
|
+
if (!members) {
|
|
1090
|
+
return { isOverride: false, isShadow: false };
|
|
1091
|
+
}
|
|
1092
|
+
// Check if base class has this member
|
|
1093
|
+
const has = memberKind === "method"
|
|
1094
|
+
? members.methods.has(memberName)
|
|
1095
|
+
: members.properties.has(memberName);
|
|
1096
|
+
// In TypeScript, all methods can be overridden (no `final` keyword)
|
|
1097
|
+
return has
|
|
1098
|
+
? { isOverride: true, isShadow: false }
|
|
1099
|
+
: { isOverride: false, isShadow: false };
|
|
1100
|
+
};
|
|
1101
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
1102
|
+
// typeFromSyntax — Convert captured type syntax to IrType
|
|
1103
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
1104
|
+
/**
|
|
1105
|
+
* Convert a captured type syntax to IrType.
|
|
1106
|
+
*
|
|
1107
|
+
* This method takes a TypeSyntaxId handle (opaque to caller) and looks up
|
|
1108
|
+
* the captured TypeNode in the HandleRegistry, then converts it.
|
|
1109
|
+
*
|
|
1110
|
+
* ALICE'S SPEC (Phase 2): TypeSystem receives opaque handles, not ts.TypeNode.
|
|
1111
|
+
*/
|
|
1112
|
+
export const typeFromSyntax = (state, typeSyntaxId) => {
|
|
1113
|
+
const syntaxInfo = state.handleRegistry.getTypeSyntax(typeSyntaxId);
|
|
1114
|
+
if (!syntaxInfo) {
|
|
1115
|
+
// Invalid handle - return unknownType
|
|
1116
|
+
return { kind: "unknownType" };
|
|
1117
|
+
}
|
|
1118
|
+
// Phase 5: convertTypeNode accepts unknown, cast is inside type-system/internal
|
|
1119
|
+
return convertTypeNode(state, syntaxInfo.typeNode);
|
|
1120
|
+
};
|
|
1121
|
+
//# sourceMappingURL=type-system-inference.js.map
|