@typecad/cuttlefish 0.1.0-alpha.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/LICENSE +21 -0
- package/README.md +79 -0
- package/dist/api/board-types.d.ts +1 -0
- package/dist/api/board-types.js +4 -0
- package/dist/api/capabilities.d.ts +12 -0
- package/dist/api/capabilities.js +1 -0
- package/dist/api/config.d.ts +120 -0
- package/dist/api/config.js +7 -0
- package/dist/api/index.d.ts +5 -0
- package/dist/api/index.js +2 -0
- package/dist/api/schema/builder.d.ts +14 -0
- package/dist/api/schema/builder.js +15 -0
- package/dist/api/schema/index.d.ts +2 -0
- package/dist/api/schema/index.js +1 -0
- package/dist/api/schema/types.d.ts +257 -0
- package/dist/api/schema/types.js +4 -0
- package/dist/api/shared/async-runtime-static.d.ts +8 -0
- package/dist/api/shared/async-runtime-static.js +201 -0
- package/dist/api/shared/async-types.d.ts +42 -0
- package/dist/api/shared/async-types.js +8 -0
- package/dist/api/shared/board-resolver.d.ts +12 -0
- package/dist/api/shared/board-resolver.js +7 -0
- package/dist/api/shared/cpp-type-ir.d.ts +229 -0
- package/dist/api/shared/cpp-type-ir.js +672 -0
- package/dist/api/shared/display-adapter.d.ts +12 -0
- package/dist/api/shared/display-adapter.js +145 -0
- package/dist/api/shared/display-adapters/eink-mono.d.ts +2 -0
- package/dist/api/shared/display-adapters/eink-mono.js +53 -0
- package/dist/api/shared/display-adapters/sdl.d.ts +2 -0
- package/dist/api/shared/display-adapters/sdl.js +452 -0
- package/dist/api/shared/display-adapters/ssd1309.d.ts +2 -0
- package/dist/api/shared/display-adapters/ssd1309.js +136 -0
- package/dist/api/shared/display-adapters/st7796.d.ts +2 -0
- package/dist/api/shared/display-adapters/st7796.js +132 -0
- package/dist/api/shared/display-capabilities.d.ts +45 -0
- package/dist/api/shared/display-capabilities.js +54 -0
- package/dist/api/shared/display-op-ir.d.ts +62 -0
- package/dist/api/shared/display-op-ir.js +19 -0
- package/dist/api/shared/display-profile.d.ts +265 -0
- package/dist/api/shared/display-profile.js +338 -0
- package/dist/api/shared/graphics-strategy.d.ts +29 -0
- package/dist/api/shared/graphics-strategy.js +11 -0
- package/dist/api/shared/hal-op-ir.d.ts +393 -0
- package/dist/api/shared/hal-op-ir.js +18 -0
- package/dist/api/shared/index.d.ts +26 -0
- package/dist/api/shared/index.js +21 -0
- package/dist/api/shared/ir-core.d.ts +363 -0
- package/dist/api/shared/ir-core.js +8 -0
- package/dist/api/shared/ir-declarations.d.ts +201 -0
- package/dist/api/shared/ir-declarations.js +26 -0
- package/dist/api/shared/ir.d.ts +85 -0
- package/dist/api/shared/ir.js +13 -0
- package/dist/api/shared/platform-strategy.d.ts +402 -0
- package/dist/api/shared/platform-strategy.js +14 -0
- package/dist/api/shared/polyfill-helper-registry.d.ts +11 -0
- package/dist/api/shared/polyfill-helper-registry.js +86 -0
- package/dist/api/shared/polyfill-types.d.ts +33 -0
- package/dist/api/shared/polyfill-types.js +76 -0
- package/dist/api/shared/promise-runtime.d.ts +10 -0
- package/dist/api/shared/promise-runtime.js +244 -0
- package/dist/api/shared/snprintf-types.d.ts +29 -0
- package/dist/api/shared/snprintf-types.js +8 -0
- package/dist/api/shared/string-method-registry.d.ts +53 -0
- package/dist/api/shared/string-method-registry.js +168 -0
- package/dist/api/shared/toolchain-types.d.ts +63 -0
- package/dist/api/shared/toolchain-types.js +71 -0
- package/dist/api/shared/types.d.ts +50 -0
- package/dist/api/shared/types.js +6 -0
- package/dist/ast/parse.d.ts +2 -0
- package/dist/ast/parse.js +4 -0
- package/dist/cache.d.ts +26 -0
- package/dist/cache.js +95 -0
- package/dist/cli-utils.d.ts +37 -0
- package/dist/cli-utils.js +250 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +635 -0
- package/dist/config-loader.d.ts +78 -0
- package/dist/config-loader.js +508 -0
- package/dist/config-schema.d.ts +233 -0
- package/dist/config-schema.js +83 -0
- package/dist/create/board-checklist.d.ts +2 -0
- package/dist/create/board-checklist.js +52 -0
- package/dist/create/board-codegen.d.ts +9 -0
- package/dist/create/board-codegen.js +238 -0
- package/dist/create/board-generators.d.ts +12 -0
- package/dist/create/board-generators.js +652 -0
- package/dist/create/board-spec.d.ts +640 -0
- package/dist/create/board-spec.js +215 -0
- package/dist/create/eslint-rules-template.d.ts +2 -0
- package/dist/create/eslint-rules-template.js +672 -0
- package/dist/create/index.d.ts +11 -0
- package/dist/create/index.js +8 -0
- package/dist/create/init-scaffold.d.ts +27 -0
- package/dist/create/init-scaffold.js +150 -0
- package/dist/create/init-templates.d.ts +24 -0
- package/dist/create/init-templates.js +379 -0
- package/dist/create/init-wizard.d.ts +8 -0
- package/dist/create/init-wizard.js +168 -0
- package/dist/debug/breakpoint-loader.d.ts +24 -0
- package/dist/debug/breakpoint-loader.js +137 -0
- package/dist/debug/index.d.ts +3 -0
- package/dist/debug/index.js +7 -0
- package/dist/debug/preprocessor.d.ts +9 -0
- package/dist/debug/preprocessor.js +214 -0
- package/dist/debug/types.d.ts +32 -0
- package/dist/debug/types.js +6 -0
- package/dist/diagnostics/diagnostics-report.d.ts +51 -0
- package/dist/diagnostics/diagnostics-report.js +333 -0
- package/dist/diagnostics/json-schema.d.ts +138 -0
- package/dist/diagnostics/json-schema.js +27 -0
- package/dist/diagnostics/md-writer.d.ts +10 -0
- package/dist/diagnostics/md-writer.js +336 -0
- package/dist/diagnostics/mermaid-builder.d.ts +65 -0
- package/dist/diagnostics/mermaid-builder.js +681 -0
- package/dist/emit/cpp-emitter.d.ts +6 -0
- package/dist/emit/cpp-emitter.js +48 -0
- package/dist/emit/emitters/class-emitter.d.ts +2 -0
- package/dist/emit/emitters/class-emitter.js +523 -0
- package/dist/emit/emitters/emitter-context.d.ts +174 -0
- package/dist/emit/emitters/emitter-context.js +1 -0
- package/dist/emit/emitters/entrypoint-synthesizer.d.ts +2 -0
- package/dist/emit/emitters/entrypoint-synthesizer.js +175 -0
- package/dist/emit/emitters/function-emitter-impl.d.ts +19 -0
- package/dist/emit/emitters/function-emitter-impl.js +428 -0
- package/dist/emit/emitters/line-appender.d.ts +15 -0
- package/dist/emit/emitters/line-appender.js +344 -0
- package/dist/emit/emitters/namespace-emitter.d.ts +2 -0
- package/dist/emit/emitters/namespace-emitter.js +324 -0
- package/dist/emit/emitters/output-finalizer.d.ts +4 -0
- package/dist/emit/emitters/output-finalizer.js +267 -0
- package/dist/emit/emitters/setup.d.ts +3 -0
- package/dist/emit/emitters/setup.js +851 -0
- package/dist/emit/emitters/top-level-prep.d.ts +2 -0
- package/dist/emit/emitters/top-level-prep.js +706 -0
- package/dist/emit/emitters/type-decl-emitter.d.ts +2 -0
- package/dist/emit/emitters/type-decl-emitter.js +251 -0
- package/dist/emit/emitters/ui-emitter.d.ts +21 -0
- package/dist/emit/emitters/ui-emitter.js +564 -0
- package/dist/emit/enum-emitter.d.ts +1 -0
- package/dist/emit/enum-emitter.js +1 -0
- package/dist/emit/expression-renderer.d.ts +283 -0
- package/dist/emit/expression-renderer.js +1477 -0
- package/dist/emit/native-helpers-emitter.d.ts +11 -0
- package/dist/emit/native-helpers-emitter.js +34 -0
- package/dist/emit/route-hal-op.d.ts +5 -0
- package/dist/emit/route-hal-op.js +13 -0
- package/dist/emit/snprintf-helpers.d.ts +17 -0
- package/dist/emit/snprintf-helpers.js +462 -0
- package/dist/emit/statement-renderer.d.ts +189 -0
- package/dist/emit/statement-renderer.js +948 -0
- package/dist/emit/utils/async-state-machine.d.ts +42 -0
- package/dist/emit/utils/async-state-machine.js +343 -0
- package/dist/emit/utils/comment-helpers.d.ts +20 -0
- package/dist/emit/utils/comment-helpers.js +31 -0
- package/dist/emit/utils/cpp-helpers.d.ts +47 -0
- package/dist/emit/utils/cpp-helpers.js +85 -0
- package/dist/emit/utils/include-resolver.d.ts +58 -0
- package/dist/emit/utils/include-resolver.js +155 -0
- package/dist/emit/utils/index.d.ts +8 -0
- package/dist/emit/utils/index.js +12 -0
- package/dist/emit/utils/type-inference.d.ts +159 -0
- package/dist/emit/utils/type-inference.js +559 -0
- package/dist/eslint-check.d.ts +10 -0
- package/dist/eslint-check.js +102 -0
- package/dist/framework-package.d.ts +10 -0
- package/dist/framework-package.js +58 -0
- package/dist/framework-registry.d.ts +39 -0
- package/dist/framework-registry.js +30 -0
- package/dist/incremental-cache.d.ts +116 -0
- package/dist/incremental-cache.js +335 -0
- package/dist/ir/adc-range-validation.d.ts +11 -0
- package/dist/ir/adc-range-validation.js +250 -0
- package/dist/ir/ast-node-utils.d.ts +8 -0
- package/dist/ir/ast-node-utils.js +32 -0
- package/dist/ir/board-pin-utils.d.ts +13 -0
- package/dist/ir/board-pin-utils.js +65 -0
- package/dist/ir/board-resolver.d.ts +36 -0
- package/dist/ir/board-resolver.js +437 -0
- package/dist/ir/build-ir-state.d.ts +167 -0
- package/dist/ir/build-ir-state.js +306 -0
- package/dist/ir/build-ir.d.ts +2 -0
- package/dist/ir/build-ir.js +808 -0
- package/dist/ir/call-graph.d.ts +35 -0
- package/dist/ir/call-graph.js +194 -0
- package/dist/ir/compile-time-only.d.ts +2 -0
- package/dist/ir/compile-time-only.js +16 -0
- package/dist/ir/declaration-builders.d.ts +9 -0
- package/dist/ir/declaration-builders.js +608 -0
- package/dist/ir/entry-points.d.ts +30 -0
- package/dist/ir/entry-points.js +191 -0
- package/dist/ir/expression-to-ir.d.ts +5 -0
- package/dist/ir/expression-to-ir.js +2249 -0
- package/dist/ir/extract-property-chain.d.ts +10 -0
- package/dist/ir/extract-property-chain.js +30 -0
- package/dist/ir/feature-prescan.d.ts +3 -0
- package/dist/ir/feature-prescan.js +43 -0
- package/dist/ir/feature-registry.d.ts +30 -0
- package/dist/ir/feature-registry.js +816 -0
- package/dist/ir/filter.d.ts +7 -0
- package/dist/ir/filter.js +85 -0
- package/dist/ir/function-builder.d.ts +19 -0
- package/dist/ir/function-builder.js +670 -0
- package/dist/ir/hal/hal-emitter.d.ts +62 -0
- package/dist/ir/hal/hal-emitter.js +735 -0
- package/dist/ir/hal/hal-parser.d.ts +61 -0
- package/dist/ir/hal/hal-parser.js +473 -0
- package/dist/ir/hal/hal-plugins.d.ts +34 -0
- package/dist/ir/hal/hal-plugins.js +706 -0
- package/dist/ir/hal-resolver.d.ts +5 -0
- package/dist/ir/hal-resolver.js +5 -0
- package/dist/ir/heap-analysis.d.ts +8 -0
- package/dist/ir/heap-analysis.js +350 -0
- package/dist/ir/heap-array-validation.d.ts +24 -0
- package/dist/ir/heap-array-validation.js +29 -0
- package/dist/ir/identifier-collector.d.ts +18 -0
- package/dist/ir/identifier-collector.js +439 -0
- package/dist/ir/interrupt-analysis.d.ts +39 -0
- package/dist/ir/interrupt-analysis.js +467 -0
- package/dist/ir/memory-budget-validation.d.ts +10 -0
- package/dist/ir/memory-budget-validation.js +86 -0
- package/dist/ir/namespace-builder.d.ts +7 -0
- package/dist/ir/namespace-builder.js +152 -0
- package/dist/ir/ownership-analysis.d.ts +9 -0
- package/dist/ir/ownership-analysis.js +1207 -0
- package/dist/ir/peripheral-ownership.d.ts +3 -0
- package/dist/ir/peripheral-ownership.js +152 -0
- package/dist/ir/peripheral-symbols.d.ts +7 -0
- package/dist/ir/peripheral-symbols.js +57 -0
- package/dist/ir/peripheral-usage.d.ts +54 -0
- package/dist/ir/peripheral-usage.js +691 -0
- package/dist/ir/peripheral-validation.d.ts +8 -0
- package/dist/ir/peripheral-validation.js +77 -0
- package/dist/ir/pin-alias-conflict.d.ts +4 -0
- package/dist/ir/pin-alias-conflict.js +34 -0
- package/dist/ir/pin-capability-validation.d.ts +6 -0
- package/dist/ir/pin-capability-validation.js +413 -0
- package/dist/ir/pin-mode-validation.d.ts +10 -0
- package/dist/ir/pin-mode-validation.js +301 -0
- package/dist/ir/pin-safety.d.ts +11 -0
- package/dist/ir/pin-safety.js +58 -0
- package/dist/ir/program-analysis.d.ts +44 -0
- package/dist/ir/program-analysis.js +589 -0
- package/dist/ir/pulldown-validation.d.ts +7 -0
- package/dist/ir/pulldown-validation.js +49 -0
- package/dist/ir/pwm-timer-sharing.d.ts +4 -0
- package/dist/ir/pwm-timer-sharing.js +93 -0
- package/dist/ir/reachability.d.ts +68 -0
- package/dist/ir/reachability.js +224 -0
- package/dist/ir/register-decorators.d.ts +6 -0
- package/dist/ir/register-decorators.js +49 -0
- package/dist/ir/render-expr.d.ts +4 -0
- package/dist/ir/render-expr.js +127 -0
- package/dist/ir/resource-analysis.d.ts +19 -0
- package/dist/ir/resource-analysis.js +153 -0
- package/dist/ir/statement-to-ir.d.ts +23 -0
- package/dist/ir/statement-to-ir.js +349 -0
- package/dist/ir/symbol-table.d.ts +68 -0
- package/dist/ir/symbol-table.js +179 -0
- package/dist/ir/symbol-types.d.ts +56 -0
- package/dist/ir/symbol-types.js +107 -0
- package/dist/ir/timer0-pwm-timing-conflict.d.ts +4 -0
- package/dist/ir/timer0-pwm-timing-conflict.js +71 -0
- package/dist/ir/timing-validation.d.ts +7 -0
- package/dist/ir/timing-validation.js +95 -0
- package/dist/ir/transformers/array-methods.d.ts +8 -0
- package/dist/ir/transformers/array-methods.js +493 -0
- package/dist/ir/transformers/call-statement.d.ts +5 -0
- package/dist/ir/transformers/call-statement.js +758 -0
- package/dist/ir/transformers/callback-context-registry.d.ts +20 -0
- package/dist/ir/transformers/callback-context-registry.js +55 -0
- package/dist/ir/transformers/canvas-lowering.d.ts +42 -0
- package/dist/ir/transformers/canvas-lowering.js +249 -0
- package/dist/ir/transformers/control-flow.d.ts +8 -0
- package/dist/ir/transformers/control-flow.js +508 -0
- package/dist/ir/transformers/expressions.d.ts +7 -0
- package/dist/ir/transformers/expressions.js +406 -0
- package/dist/ir/transformers/hal-call-resolver.d.ts +29 -0
- package/dist/ir/transformers/hal-call-resolver.js +274 -0
- package/dist/ir/transformers/hal-emit-helpers.d.ts +14 -0
- package/dist/ir/transformers/hal-emit-helpers.js +63 -0
- package/dist/ir/transformers/namespace-methods.d.ts +20 -0
- package/dist/ir/transformers/namespace-methods.js +110 -0
- package/dist/ir/transformers/register-assignment.d.ts +5 -0
- package/dist/ir/transformers/register-assignment.js +56 -0
- package/dist/ir/transformers/ui-call-resolver.d.ts +149 -0
- package/dist/ir/transformers/ui-call-resolver.js +1136 -0
- package/dist/ir/transformers/ui-callback-lowering.d.ts +62 -0
- package/dist/ir/transformers/ui-callback-lowering.js +623 -0
- package/dist/ir/transformers/ui-mount.d.ts +20 -0
- package/dist/ir/transformers/ui-mount.js +35 -0
- package/dist/ir/transformers/ui-reactive.d.ts +68 -0
- package/dist/ir/transformers/ui-reactive.js +129 -0
- package/dist/ir/transformers/variables.d.ts +14 -0
- package/dist/ir/transformers/variables.js +1045 -0
- package/dist/ir/try-catch-validation.d.ts +26 -0
- package/dist/ir/try-catch-validation.js +128 -0
- package/dist/ir/type-resolution.d.ts +31 -0
- package/dist/ir/type-resolution.js +977 -0
- package/dist/ir/ui-element-auto-wire.d.ts +50 -0
- package/dist/ir/ui-element-auto-wire.js +218 -0
- package/dist/ir/unit-suspicion-validation.d.ts +12 -0
- package/dist/ir/unit-suspicion-validation.js +296 -0
- package/dist/ir/utils/walk-ir.d.ts +6 -0
- package/dist/ir/utils/walk-ir.js +162 -0
- package/dist/ir/validation-orchestrator.d.ts +4 -0
- package/dist/ir/validation-orchestrator.js +45 -0
- package/dist/libdef/base-class-resolver.d.ts +23 -0
- package/dist/libdef/base-class-resolver.js +50 -0
- package/dist/libdef/cpp-to-decl.d.ts +34 -0
- package/dist/libdef/cpp-to-decl.js +584 -0
- package/dist/libdef/header-parser.d.ts +53 -0
- package/dist/libdef/header-parser.js +269 -0
- package/dist/libdef/registry.d.ts +10 -0
- package/dist/libdef/registry.js +142 -0
- package/dist/mapping/peripheral-names.d.ts +23 -0
- package/dist/mapping/peripheral-names.js +63 -0
- package/dist/mapping/source-map.d.ts +46 -0
- package/dist/mapping/source-map.js +207 -0
- package/dist/orchestrator/dts-generator.d.ts +17 -0
- package/dist/orchestrator/dts-generator.js +83 -0
- package/dist/orchestrator/graph-builder.d.ts +18 -0
- package/dist/orchestrator/graph-builder.js +218 -0
- package/dist/orchestrator/semantic-facts-verifier.d.ts +38 -0
- package/dist/orchestrator/semantic-facts-verifier.js +121 -0
- package/dist/orchestrator/semantic-facts.d.ts +141 -0
- package/dist/orchestrator/semantic-facts.js +652 -0
- package/dist/orchestrator/type-checker.d.ts +39 -0
- package/dist/orchestrator/type-checker.js +760 -0
- package/dist/platform/async-runtime.d.ts +8 -0
- package/dist/platform/async-runtime.js +26 -0
- package/dist/platform/generic-strategy.d.ts +101 -0
- package/dist/platform/generic-strategy.js +289 -0
- package/dist/platform/index.d.ts +4 -0
- package/dist/platform/index.js +9 -0
- package/dist/platform/registry.d.ts +21 -0
- package/dist/platform/registry.js +42 -0
- package/dist/platform/toolchain.d.ts +4 -0
- package/dist/platform/toolchain.js +43 -0
- package/dist/preview/client.d.ts +1 -0
- package/dist/preview/client.js +137 -0
- package/dist/preview/server.d.ts +5 -0
- package/dist/preview/server.js +199 -0
- package/dist/profiler/index.d.ts +28 -0
- package/dist/profiler/index.js +28 -0
- package/dist/profiler/profiler.d.ts +95 -0
- package/dist/profiler/profiler.js +338 -0
- package/dist/profiler/types.d.ts +87 -0
- package/dist/profiler/types.js +12 -0
- package/dist/stores/display-profile-store.d.ts +16 -0
- package/dist/stores/display-profile-store.js +48 -0
- package/dist/stores/theme-store.d.ts +13 -0
- package/dist/stores/theme-store.js +30 -0
- package/dist/testing.d.ts +45 -0
- package/dist/testing.js +47 -0
- package/dist/transpile/resolution.d.ts +29 -0
- package/dist/transpile/resolution.js +282 -0
- package/dist/transpile.d.ts +3 -0
- package/dist/transpile.js +722 -0
- package/dist/types.d.ts +217 -0
- package/dist/types.js +1 -0
- package/dist/ui/ui-bridge.d.ts +4 -0
- package/dist/ui/ui-bridge.js +34 -0
- package/dist/ui-hook.d.ts +84 -0
- package/dist/ui-hook.js +45 -0
- package/dist/utils/cli.d.ts +3 -0
- package/dist/utils/cli.js +463 -0
- package/dist/utils/fs.d.ts +4 -0
- package/dist/utils/fs.js +23 -0
- package/dist/utils/logger.d.ts +2 -0
- package/dist/utils/logger.js +8 -0
- package/dist/utils/strings.d.ts +35 -0
- package/dist/utils/strings.js +142 -0
- package/dist/utils/ui.d.ts +66 -0
- package/dist/utils/ui.js +149 -0
- package/dist/watch.d.ts +35 -0
- package/dist/watch.js +111 -0
- package/package.json +127 -0
|
@@ -0,0 +1,816 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
const KIND_REGISTRY = new Map();
|
|
3
|
+
function add(kind, entry) {
|
|
4
|
+
KIND_REGISTRY.set(kind, entry);
|
|
5
|
+
}
|
|
6
|
+
const UNSUPPORTED_OBJECT_RUNTIME_METHODS = new Set([
|
|
7
|
+
"assign",
|
|
8
|
+
"freeze",
|
|
9
|
+
"fromEntries",
|
|
10
|
+
"defineProperty",
|
|
11
|
+
"defineProperties",
|
|
12
|
+
"create",
|
|
13
|
+
"getPrototypeOf",
|
|
14
|
+
"setPrototypeOf",
|
|
15
|
+
"getOwnPropertyDescriptor",
|
|
16
|
+
]);
|
|
17
|
+
const UNSUPPORTED_DYNAMIC_CALL_METHODS = new Set(["bind", "call", "apply"]);
|
|
18
|
+
const UNSUPPORTED_RUNTIME_GLOBALS = new Set(["Proxy", "Reflect", "Symbol", "WeakRef", "FinalizationRegistry"]);
|
|
19
|
+
// Array.* constructor statics that are not lowered (no JS array runtime). Note
|
|
20
|
+
// `Array.isArray` IS lowered (a type check that resolves at compile time), so
|
|
21
|
+
// it is intentionally absent here. Demo #28 Finding A review.
|
|
22
|
+
const UNSUPPORTED_ARRAY_STATIC_METHODS = new Set(["from", "of"]);
|
|
23
|
+
const ASSIGNMENT_OPERATOR_KINDS = new Set([
|
|
24
|
+
ts.SyntaxKind.EqualsToken,
|
|
25
|
+
ts.SyntaxKind.PlusEqualsToken,
|
|
26
|
+
ts.SyntaxKind.MinusEqualsToken,
|
|
27
|
+
ts.SyntaxKind.AsteriskEqualsToken,
|
|
28
|
+
ts.SyntaxKind.AsteriskAsteriskEqualsToken,
|
|
29
|
+
ts.SyntaxKind.SlashEqualsToken,
|
|
30
|
+
ts.SyntaxKind.PercentEqualsToken,
|
|
31
|
+
ts.SyntaxKind.LessThanLessThanEqualsToken,
|
|
32
|
+
ts.SyntaxKind.GreaterThanGreaterThanEqualsToken,
|
|
33
|
+
ts.SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken,
|
|
34
|
+
ts.SyntaxKind.AmpersandEqualsToken,
|
|
35
|
+
ts.SyntaxKind.BarEqualsToken,
|
|
36
|
+
ts.SyntaxKind.CaretEqualsToken,
|
|
37
|
+
ts.SyntaxKind.BarBarEqualsToken,
|
|
38
|
+
ts.SyntaxKind.AmpersandAmpersandEqualsToken,
|
|
39
|
+
ts.SyntaxKind.QuestionQuestionEqualsToken,
|
|
40
|
+
].filter((kind) => typeof kind === "number"));
|
|
41
|
+
add(ts.SyntaxKind.TaggedTemplateExpression, {
|
|
42
|
+
status: "unsupported",
|
|
43
|
+
message: "Tagged template expressions have no C++ equivalent.",
|
|
44
|
+
hint: "Use a regular template literal (backtick string) or string concatenation instead.",
|
|
45
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
46
|
+
eslint: {
|
|
47
|
+
selector: "TaggedTemplateExpression",
|
|
48
|
+
message: "[transpiler] Tagged template expressions have no C++ equivalent. Use regular template literals or string concatenation.",
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
add(ts.SyntaxKind.MetaProperty, {
|
|
52
|
+
status: "unsupported",
|
|
53
|
+
message: "Meta-property expressions (import.meta, new.target) have no C++ equivalent.",
|
|
54
|
+
hint: "Avoid import.meta and new.target; they rely on JS runtime reflection.",
|
|
55
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
56
|
+
eslint: {
|
|
57
|
+
selector: "MetaProperty",
|
|
58
|
+
message: "[transpiler] import.meta and new.target have no C++ equivalent.",
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
add(ts.SyntaxKind.RegularExpressionLiteral, {
|
|
62
|
+
status: "approximation",
|
|
63
|
+
message: "Regular expression literals are approximated with std::regex in C++.",
|
|
64
|
+
hint: "std::regex has different syntax and performance characteristics than JS RegExp.",
|
|
65
|
+
code: "TS2CPP_APPROXIMATE",
|
|
66
|
+
eslint: {
|
|
67
|
+
selector: "Literal[regex]",
|
|
68
|
+
message: "[transpiler] regex literals are approximated with std::regex in C++ — JS RegExp syntax/perf do not carry over.",
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
add(ts.SyntaxKind.SpreadAssignment, {
|
|
72
|
+
status: "unsupported",
|
|
73
|
+
message: "Object spread ({...obj}) has no C++ equivalent.",
|
|
74
|
+
hint: "Manually copy each property, or use a Map with an insert/merge method.",
|
|
75
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
76
|
+
eslint: {
|
|
77
|
+
selector: "ObjectExpression > SpreadElement",
|
|
78
|
+
message: "[transpiler] object spread ({ ...obj }) is not supported — C++ structs have fixed shape. Construct the object field-by-field instead.",
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
add(ts.SyntaxKind.ComputedPropertyName, {
|
|
82
|
+
status: "unsupported",
|
|
83
|
+
message: "Computed property names ({ [expr]: value }) have no C++ equivalent.",
|
|
84
|
+
hint: "Use a Map<string, T> for dynamic keys, or use fixed property names.",
|
|
85
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
86
|
+
eslint: {
|
|
87
|
+
selector: "ObjectExpression > Property[computed=true]",
|
|
88
|
+
message: "[transpiler] Computed property names ({ [expr]: value }) have no C++ equivalent. Use fixed property names, or a Map<string, T> with .set().",
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
// No `.eslint`: explicit `any` is owned by the core @typescript-eslint/no-explicit-any
|
|
92
|
+
// rule configured separately in the scaffolded eslint.config.mjs.
|
|
93
|
+
add(ts.SyntaxKind.AnyKeyword, {
|
|
94
|
+
status: "unsupported",
|
|
95
|
+
message: "Explicit 'any' has no safe C++ lowering (transpiler would emit 'auto' and lose type safety).",
|
|
96
|
+
hint: "Annotate with a concrete type. For truly dynamic values, use 'unknown' and narrow with type guards.",
|
|
97
|
+
code: "TS2CPP_EXPLICIT_ANY",
|
|
98
|
+
});
|
|
99
|
+
add(ts.SyntaxKind.BigIntKeyword, {
|
|
100
|
+
status: "unsupported",
|
|
101
|
+
message: "The 'bigint' type has no supported embedded C++ lowering.",
|
|
102
|
+
hint: "Use number with an explicit fixed-width type such as int32_t, uint32_t, or int64_t.",
|
|
103
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
104
|
+
eslint: {
|
|
105
|
+
selector: "TSBigIntKeyword",
|
|
106
|
+
message: "[transpiler] bigint is not supported (no C++ equivalent for embedded targets). Use number with an explicit fixed-width type (int32_t/int64_t).",
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
add(ts.SyntaxKind.BigIntLiteral, {
|
|
110
|
+
status: "unsupported",
|
|
111
|
+
message: "BigInt literals have no supported embedded C++ lowering.",
|
|
112
|
+
hint: "Use a number literal with an explicit fixed-width type annotation.",
|
|
113
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
114
|
+
eslint: {
|
|
115
|
+
selector: "Literal[bigInt=true]",
|
|
116
|
+
message: "[transpiler] BigInt literals are not supported (no C++ equivalent for embedded targets). Use a number literal with an explicit fixed-width type.",
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
add(ts.SyntaxKind.NeverKeyword, {
|
|
120
|
+
status: "unsupported",
|
|
121
|
+
message: "The 'never' type has no meaningful C++ lowering.",
|
|
122
|
+
hint: "Use void for functions that do not return a value, or an explicit error/result type.",
|
|
123
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
124
|
+
eslint: {
|
|
125
|
+
selector: "TSNeverKeyword",
|
|
126
|
+
message: "[transpiler] the `never` type has no meaningful C++ lowering. Avoid it.",
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
add(ts.SyntaxKind.IndexedAccessType, {
|
|
130
|
+
status: "unsupported",
|
|
131
|
+
message: "Indexed access types (T[K]) have no deterministic C++ lowering.",
|
|
132
|
+
hint: "Use the concrete field type directly.",
|
|
133
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
134
|
+
eslint: {
|
|
135
|
+
selector: "TSIndexedAccessType",
|
|
136
|
+
message: "[transpiler] indexed access types (T[K]) are not supported (no C++ equivalent). Use the concrete field type directly.",
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
add(ts.SyntaxKind.ConditionalType, {
|
|
140
|
+
status: "unsupported",
|
|
141
|
+
message: "Conditional types (T extends U ? X : Y) are type-level logic with no deterministic C++ lowering.",
|
|
142
|
+
hint: "Write an explicit type alias or overload with concrete types.",
|
|
143
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
144
|
+
eslint: {
|
|
145
|
+
selector: "TSTypeAliasDeclaration > TSConditionalType",
|
|
146
|
+
message: "[transpiler] conditional types (T extends X ? A : B) are not supported — they leak generic type parameters into generated C++.",
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
add(ts.SyntaxKind.MappedType, {
|
|
150
|
+
status: "unsupported",
|
|
151
|
+
message: "Mapped types ({ [K in keyof T]: U }) have no deterministic C++ lowering.",
|
|
152
|
+
hint: "Define an explicit interface or struct with the fields you need.",
|
|
153
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
154
|
+
eslint: {
|
|
155
|
+
selector: "TSTypeAliasDeclaration > TSMappedType",
|
|
156
|
+
message: "[transpiler] mapped types ({ [K in keyof T]: U }) are not supported — they leak generic type parameters into generated C++.",
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
add(ts.SyntaxKind.TemplateLiteralType, {
|
|
160
|
+
status: "unsupported",
|
|
161
|
+
message: "Template literal types have no C++ equivalent.",
|
|
162
|
+
hint: "Use string at runtime, or define an explicit string enum/union pattern.",
|
|
163
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
164
|
+
eslint: {
|
|
165
|
+
selector: "TSTemplateLiteralType",
|
|
166
|
+
message: "[transpiler] template literal types have no C++ equivalent. Use a string union or an explicit enum.",
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
export function getKindEntry(kind) {
|
|
170
|
+
return KIND_REGISTRY.get(kind);
|
|
171
|
+
}
|
|
172
|
+
// Iterate the kind registry (used by the eslint-parity test to assert every
|
|
173
|
+
// kind either contributes a selector or is explicitly opted out).
|
|
174
|
+
export function kindRegistryEntries() {
|
|
175
|
+
return [...KIND_REGISTRY.entries()];
|
|
176
|
+
}
|
|
177
|
+
// Kinds deliberately without an `.eslint` selector. Each must be documented:
|
|
178
|
+
// - AnyKeyword — owned by the @typescript-eslint/no-explicit-any core rule.
|
|
179
|
+
const ESLINT_OPT_OUT_KINDS = new Set([
|
|
180
|
+
ts.SyntaxKind.AnyKeyword,
|
|
181
|
+
]);
|
|
182
|
+
// Kind-based selectors: one per KIND_REGISTRY entry that has `.eslint` set.
|
|
183
|
+
function kindBasedLintRules() {
|
|
184
|
+
const rules = [];
|
|
185
|
+
for (const entry of KIND_REGISTRY.values()) {
|
|
186
|
+
if (entry.eslint) {
|
|
187
|
+
rules.push({
|
|
188
|
+
selector: entry.eslint.selector,
|
|
189
|
+
message: entry.eslint.message,
|
|
190
|
+
source: "kind",
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return rules;
|
|
195
|
+
}
|
|
196
|
+
// Context-sensitive selectors: patterns that also live in checkContextSensitive
|
|
197
|
+
// as imperative visitors, but CAN additionally be expressed as a static
|
|
198
|
+
// `no-restricted-syntax` selector for real-time editor warnings. Kept here so
|
|
199
|
+
// that all editor-time selectors live in one place.
|
|
200
|
+
//
|
|
201
|
+
// NOTE on async/generator/yield severity: these are flagged as `"error"` by
|
|
202
|
+
// ESLint (matching the prior hand-maintained config) but the transpiler only
|
|
203
|
+
// emits a `TS2CPP_ASYNC_STUB` *warning* at build time and emits stub code.
|
|
204
|
+
// The severity mismatch is intentional and documented here — it is not a bug
|
|
205
|
+
// this refactor introduces or should silently "fix".
|
|
206
|
+
const CONTEXT_LINT_RULES = [
|
|
207
|
+
{
|
|
208
|
+
selector: "ForOfStatement[await=true]",
|
|
209
|
+
message: "[transpiler] for await...of is unsupported (requires an async runtime absent on bare metal). Use a synchronous for...of loop.",
|
|
210
|
+
source: "context",
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
selector: "CallExpression[callee.type='FunctionExpression']",
|
|
214
|
+
message: "[transpiler] immediately-invoked function expressions (IIFEs) are not supported — the body is not inlined and the `function` keyword is emitted verbatim. Assign to a const or define a named top-level function.",
|
|
215
|
+
source: "context",
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
selector: "CallExpression[callee.type='ArrowFunctionExpression']",
|
|
219
|
+
message: "[transpiler] immediately-invoked arrow expressions (() => {...})() are not supported — the body is not inlined. Assign to a const or define a named top-level function.",
|
|
220
|
+
source: "context",
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
selector: "TSTypeOperator[type='keyof']",
|
|
224
|
+
message: "[transpiler] the keyof operator is not supported (no C++ equivalent). Use a string union or a switch over field names.",
|
|
225
|
+
source: "context",
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
selector: "TSTypeReference > Identifier[name=/^(ReturnType|Parameters|InstanceType|ConstructorParameters|Extract|Exclude)$/]",
|
|
229
|
+
message: "[transpiler] ReturnType/Parameters/InstanceType/Extract/Exclude utility types fall back to auto and are not deterministic enough for C++ emission. Declare the concrete type explicitly.",
|
|
230
|
+
source: "context",
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
selector: "StaticBlock",
|
|
234
|
+
message: "[transpiler] static initializer blocks (static { ... }) are not supported. Initialize static fields in their declaration or the constructor.",
|
|
235
|
+
source: "context",
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
selector: "Identifier[name='Promise']",
|
|
239
|
+
message: "[transpiler] Promise is not supported (no promise runtime on bare metal). Use synchronous return values or callbacks.",
|
|
240
|
+
source: "context",
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
selector: "CallExpression > MemberExpression.callee[property.name='then']",
|
|
244
|
+
message: "[transpiler] .then() on a Promise is not supported (no promise runtime). Use synchronous return values or callbacks.",
|
|
245
|
+
source: "context",
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
selector: "FunctionDeclaration[async=true]",
|
|
249
|
+
message: "[transpiler] async functions are recognized for parse-compatibility but cannot produce correct embedded behavior (no event loop). Use a synchronous function.",
|
|
250
|
+
source: "context",
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
selector: "FunctionExpression[async=true]",
|
|
254
|
+
message: "[transpiler] async function expressions are recognized for parse-compatibility but cannot produce correct embedded behavior (no event loop). Use a synchronous function.",
|
|
255
|
+
source: "context",
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
selector: "ArrowFunctionExpression[async=true]",
|
|
259
|
+
message: "[transpiler] async arrow functions are recognized for parse-compatibility but cannot produce correct embedded behavior (no event loop). Use a synchronous arrow function.",
|
|
260
|
+
source: "context",
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
selector: "AwaitExpression",
|
|
264
|
+
message: "[transpiler] await is stripped to an inline expression — semantics are approximate and there is no event loop on bare metal. Avoid in firmware.",
|
|
265
|
+
source: "context",
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
selector: "FunctionDeclaration[generator=true]",
|
|
269
|
+
message: "[transpiler] generator functions (function*) have no coroutine runtime on bare metal and are effectively unusable. Avoid.",
|
|
270
|
+
source: "context",
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
selector: "FunctionExpression[generator=true]",
|
|
274
|
+
message: "[transpiler] generator expressions (function*) have no coroutine runtime on bare metal and are effectively unusable. Avoid.",
|
|
275
|
+
source: "context",
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
selector: "YieldExpression",
|
|
279
|
+
message: "[transpiler] yield lowers to co_yield but no coroutine runtime is wired for embedded targets. Avoid.",
|
|
280
|
+
source: "context",
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
selector: "BinaryExpression[operator='**']",
|
|
284
|
+
message: "[transpiler] the ** exponentiation operator is not a first-class emit. Use Math.pow() for reliable lowering.",
|
|
285
|
+
source: "context",
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
selector: "MemberExpression[object.name='JSON']",
|
|
289
|
+
message: "[transpiler] JSON.* is not supported (no JSON runtime on bare metal). Parse/format manually, or avoid.",
|
|
290
|
+
source: "context",
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
selector: "CallExpression > MemberExpression.callee[object.name='String'][property.name=/^(fromCharCode|fromCodePoint|raw)$/] | MemberExpression[object.name='String']",
|
|
294
|
+
message: "[transpiler] String.* static methods (fromCharCode, fromCodePoint, raw, ...) are not lowered to C++. Build the string from an explicit single-char-string lookup table instead.",
|
|
295
|
+
source: "context",
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
selector: "CallExpression > MemberExpression.callee[object.name='Number'][property.name=/^(parseInt|parseFloat|isFinite|isNaN|isInteger|isSafeInteger)$/]",
|
|
299
|
+
message: "[transpiler] Number.* static methods are not lowered to C++ (no JS number-runtime on bare metal). Use an explicit cast or a fixed-width numeric type.",
|
|
300
|
+
source: "context",
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
selector: "CallExpression > MemberExpression.callee[object.name='Array'][property.name=/^(from|of)$/]",
|
|
304
|
+
message: "[transpiler] Array.from / Array.of are not lowered to C++ (no JS array runtime). Construct the std::vector directly (a literal, a sized loop, or std::vector<...>). Array.isArray IS supported.",
|
|
305
|
+
source: "context",
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
selector: "NewExpression[callee.name='Date']",
|
|
309
|
+
message: "[transpiler] new Date() is not supported — no Date/calendar runtime on bare metal. Use millis()/micros() for elapsed time or pass an explicit value.",
|
|
310
|
+
source: "context",
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
selector: "CallExpression > MemberExpression.callee[object.name='Object'][property.name=/^(assign|freeze|fromEntries)$/]",
|
|
314
|
+
message: "[transpiler] Object.assign/freeze/fromEntries are not lowered to C++. Construct objects explicitly or use a Map.",
|
|
315
|
+
source: "context",
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
selector: "ImportExpression",
|
|
319
|
+
message: "[transpiler] dynamic import() is unsupported (no runtime loader on bare metal). Use a static top-level import.",
|
|
320
|
+
source: "context",
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
selector: "CallExpression[callee.name='require']",
|
|
324
|
+
message: "[transpiler] require() is unsupported. Use ES `import`.",
|
|
325
|
+
source: "context",
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
selector: "BinaryExpression[operator='instanceof']",
|
|
329
|
+
message: "[transpiler] instanceof has no RTTI lowering and is treated loosely. Avoid it for user-class hierarchies in firmware.",
|
|
330
|
+
source: "context",
|
|
331
|
+
},
|
|
332
|
+
{
|
|
333
|
+
selector: "CallExpression > MemberExpression.callee[object.name='Object'][property.name=/^(defineProperty|defineProperties|create|getPrototypeOf|setPrototypeOf|getOwnPropertyDescriptor)$/]",
|
|
334
|
+
message: "[transpiler] Object.defineProperty/defineProperties/create/getPrototypeOf/setPrototypeOf/getOwnPropertyDescriptor mutate or introspect object shape at runtime — no AOT C++ lowering. Avoid.",
|
|
335
|
+
source: "context",
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
selector: "CallExpression > MemberExpression.callee[property.name=/^(bind|call|apply)$/]",
|
|
339
|
+
message: "[transpiler] .bind/.call/.apply rebind `this` at call time, which has no C++ lowering (this is a fixed pointer). Call the function/method directly.",
|
|
340
|
+
source: "context",
|
|
341
|
+
// ui.bind is a recognized UI authoring call (intercepted by the
|
|
342
|
+
// transpiler's call-lowering), not Function.prototype.bind.
|
|
343
|
+
filter: "(node) => { const o = node.callee.object; return !(o && o.type === 'Identifier' && o.name === 'ui'); }",
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
selector: "NewExpression[callee.name='Function']",
|
|
347
|
+
message: "[transpiler] new Function() compiles a string at runtime — no JS runtime on bare metal. Define a named function instead.",
|
|
348
|
+
source: "context",
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
selector: "AssignmentExpression[left.type='MemberExpression'][left.property.name='__proto__']",
|
|
352
|
+
message: "[transpiler] __proto__ assignment mutates the prototype chain — no AOT C++ lowering. Use a class with extends, or a Map.",
|
|
353
|
+
source: "context",
|
|
354
|
+
},
|
|
355
|
+
];
|
|
356
|
+
// The canonical list of ESLint `no-restricted-syntax` entries rendered into
|
|
357
|
+
// the scaffolded eslint.config.mjs by generateEslintConfig().
|
|
358
|
+
export const LINT_RULES = [
|
|
359
|
+
...kindBasedLintRules(),
|
|
360
|
+
...CONTEXT_LINT_RULES,
|
|
361
|
+
];
|
|
362
|
+
// Exported so the parity test can assert that every KIND_REGISTRY entry either
|
|
363
|
+
// contributes a selector here or is explicitly opted out.
|
|
364
|
+
export { ESLINT_OPT_OUT_KINDS };
|
|
365
|
+
export function checkContextSensitive(node, sourceText) {
|
|
366
|
+
if (ts.isFunctionDeclaration(node) && node.body && !node.name) {
|
|
367
|
+
return {
|
|
368
|
+
message: "Anonymous function declarations are not supported by the C++ transpiler.",
|
|
369
|
+
hint: "Give the function a name, or assign a function expression to a named const.",
|
|
370
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
if (ts.isForOfStatement(node) && node.awaitModifier) {
|
|
374
|
+
return {
|
|
375
|
+
message: "for await...of requires async iteration runtime support and cannot be lowered to deterministic C++.",
|
|
376
|
+
hint: "Use a synchronous for...of loop over a concrete array or collection.",
|
|
377
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
if (ts.isCallExpression(node)) {
|
|
381
|
+
if (ts.isFunctionExpression(node.expression) || ts.isArrowFunction(node.expression)) {
|
|
382
|
+
return {
|
|
383
|
+
message: "Immediately-invoked function expressions are not supported by the C++ transpiler.",
|
|
384
|
+
hint: "Move the body into a named function, or assign the result through ordinary statements.",
|
|
385
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
if (ts.isIdentifier(node.expression) && UNSUPPORTED_RUNTIME_GLOBALS.has(node.expression.text)) {
|
|
389
|
+
return {
|
|
390
|
+
message: `${node.expression.text} depends on JavaScript runtime reflection and has no AOT C++ lowering.`,
|
|
391
|
+
hint: "Use explicit classes, functions, or ordinary values instead.",
|
|
392
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
if (node.expression.kind === ts.SyntaxKind.ImportKeyword) {
|
|
396
|
+
return {
|
|
397
|
+
message: "Dynamic import() has no runtime loader in generated C++.",
|
|
398
|
+
hint: "Use a static top-level import.",
|
|
399
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
if (ts.isIdentifier(node.expression) && node.expression.text === "require") {
|
|
403
|
+
return {
|
|
404
|
+
message: "require() is unsupported in the C++ transpiler.",
|
|
405
|
+
hint: "Use an ES module import at the top of the file.",
|
|
406
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
if (ts.isPropertyAccessExpression(node.expression)) {
|
|
410
|
+
const methodName = node.expression.name.text;
|
|
411
|
+
const receiver = node.expression.expression;
|
|
412
|
+
const receiverName = ts.isIdentifier(receiver) ? receiver.text : undefined;
|
|
413
|
+
if (receiverName === "Promise" || methodName === "then") {
|
|
414
|
+
return {
|
|
415
|
+
message: "Promise APIs and .then() callbacks have no deterministic embedded C++ runtime.",
|
|
416
|
+
hint: "Use synchronous return values, an explicit callback parameter, or a framework-provided async primitive.",
|
|
417
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
if (receiverName === "JSON") {
|
|
421
|
+
return {
|
|
422
|
+
message: "JSON APIs require a JavaScript JSON runtime and are not supported by the C++ transpiler.",
|
|
423
|
+
hint: "Parse or format data explicitly, or pass already-structured values.",
|
|
424
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
if (receiverName === "String") {
|
|
428
|
+
return {
|
|
429
|
+
message: `String.${methodName}() is a JavaScript String-constructor static with no C++ lowering (no JS string runtime on bare metal).`,
|
|
430
|
+
hint: "Build the string from an explicit single-char-string lookup table (e.g. const GLYPHS: string[] = [...]) rather than String.fromCharCode/fromCodePoint/raw.",
|
|
431
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
if (receiverName === "Number") {
|
|
435
|
+
return {
|
|
436
|
+
message: `Number.${methodName}() is a JavaScript Number-constructor static with no C++ lowering (no JS number runtime on bare metal).`,
|
|
437
|
+
hint: "Use an explicit C++ cast (static_cast<int>), an explicit fixed-width numeric type, or a manual implementation.",
|
|
438
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
if (receiverName === "Array" && UNSUPPORTED_ARRAY_STATIC_METHODS.has(methodName)) {
|
|
442
|
+
return {
|
|
443
|
+
message: `Array.${methodName}() is a JavaScript Array-constructor static with no C++ lowering.`,
|
|
444
|
+
hint: "Construct the std::vector directly: a literal ([...]), a sized loop, or std::vector<...> directly. Array.from/of are not lowered.",
|
|
445
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
if (receiverName === "Object" && UNSUPPORTED_OBJECT_RUNTIME_METHODS.has(methodName)) {
|
|
449
|
+
return {
|
|
450
|
+
message: `Object.${methodName}() mutates or introspects runtime object shape and has no deterministic C++ lowering.`,
|
|
451
|
+
hint: "Construct fixed-shape structs explicitly, or use a Map for dynamic key/value data.",
|
|
452
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
if (receiverName === "Reflect") {
|
|
456
|
+
return {
|
|
457
|
+
message: "Reflect APIs depend on JavaScript runtime reflection and have no AOT C++ lowering.",
|
|
458
|
+
hint: "Use explicit property access, methods, or a Map instead.",
|
|
459
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
if (UNSUPPORTED_DYNAMIC_CALL_METHODS.has(methodName)) {
|
|
463
|
+
// ui.bind is a recognized UI authoring call (intercepted by
|
|
464
|
+
// ui-call-resolver), not Function.prototype.bind. The name collides;
|
|
465
|
+
// exempt the `ui` receiver so the call-lowering can run.
|
|
466
|
+
if (methodName === "bind" && receiverName === "ui") {
|
|
467
|
+
// fall through — not an unsupported pattern
|
|
468
|
+
}
|
|
469
|
+
else {
|
|
470
|
+
return {
|
|
471
|
+
message: `.${methodName}() rebinds call-time function context and has no deterministic C++ lowering.`,
|
|
472
|
+
hint: "Call the function or method directly, or pass the receiver as an explicit argument.",
|
|
473
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
if (ts.isClassStaticBlockDeclaration?.(node) || node.kind === ts.SyntaxKind.ClassStaticBlockDeclaration) {
|
|
480
|
+
return {
|
|
481
|
+
message: "Static initializer blocks have no deterministic C++ lowering.",
|
|
482
|
+
hint: "Initialize static fields in their declaration, or move setup into an explicit static method.",
|
|
483
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
if (ts.isNewExpression(node)) {
|
|
487
|
+
if (ts.isIdentifier(node.expression) && node.expression.text === "Function") {
|
|
488
|
+
return {
|
|
489
|
+
message: "new Function() compiles a string at runtime and has no AOT C++ lowering.",
|
|
490
|
+
hint: "Define a named function in TypeScript instead.",
|
|
491
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
if (ts.isIdentifier(node.expression) && (node.expression.text === "Promise" || UNSUPPORTED_RUNTIME_GLOBALS.has(node.expression.text))) {
|
|
495
|
+
return {
|
|
496
|
+
message: `new ${node.expression.text}() requires JavaScript runtime behavior that generated C++ does not provide.`,
|
|
497
|
+
hint: "Use explicit classes/functions or synchronous values instead.",
|
|
498
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
// new Date() — there is no Date/calendar runtime on bare metal. Lowering
|
|
502
|
+
// previously emitted `Date* d = new Date();` verbatim (an undefined `Date`
|
|
503
|
+
// type), failing at g++ time. Demo #28 Finding A review.
|
|
504
|
+
if (ts.isIdentifier(node.expression) && node.expression.text === "Date") {
|
|
505
|
+
return {
|
|
506
|
+
message: "new Date() requires a Date/calendar runtime that generated C++ does not provide.",
|
|
507
|
+
hint: "Use millis()/micros() for elapsed time, or pass an explicit time value.",
|
|
508
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
// new Array(...) WITHOUT a type argument. The TYPED form
|
|
512
|
+
// `new Array<E>(n)` IS lowered (→ `std::vector<E>(n)`, demo #29 Finding B),
|
|
513
|
+
// but the UNTYPED `new Array(n)` carries no element type to lower to, so it
|
|
514
|
+
// cannot pick a C++ element type. Reject it at build time with a clear
|
|
515
|
+
// source-located diagnostic and a one-line fix (add the `<E>` argument),
|
|
516
|
+
// rather than letting it fall through to the verbatim `new Array(...)` emit
|
|
517
|
+
// that fails at g++ time with the opaque "'Array' does not name a type".
|
|
518
|
+
if (ts.isIdentifier(node.expression) && node.expression.text === "Array"
|
|
519
|
+
&& (!node.typeArguments || node.typeArguments.length === 0)) {
|
|
520
|
+
return {
|
|
521
|
+
message: "new Array(...) without an explicit element type cannot be lowered: the C++ element type is unknown.",
|
|
522
|
+
hint: "Use the typed form new Array<ElementType>(n) (lowered to std::vector<ElementType>(n)), or an array literal [].",
|
|
523
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
// Syntactic heuristic: `new Identifier()` where Identifier names an
|
|
527
|
+
// interface declared in the same file. Accurate cross-file symbol
|
|
528
|
+
// resolution is upgraded in the Phase 3 TypeChecker pass; this catches
|
|
529
|
+
// the common single-file case without any checker infrastructure.
|
|
530
|
+
const expr = node.expression;
|
|
531
|
+
if (ts.isIdentifier(expr)) {
|
|
532
|
+
const name = expr.text;
|
|
533
|
+
const sourceFile = node.getSourceFile();
|
|
534
|
+
let isInterface = false;
|
|
535
|
+
const visit = (n) => {
|
|
536
|
+
if (ts.isInterfaceDeclaration(n) && n.name?.text === name) {
|
|
537
|
+
isInterface = true;
|
|
538
|
+
}
|
|
539
|
+
if (!isInterface) {
|
|
540
|
+
ts.forEachChild(n, visit);
|
|
541
|
+
}
|
|
542
|
+
};
|
|
543
|
+
ts.forEachChild(sourceFile, visit);
|
|
544
|
+
if (isInterface) {
|
|
545
|
+
return {
|
|
546
|
+
message: `Cannot instantiate interface '${name}' — only class constructors are supported in C++.`,
|
|
547
|
+
hint: `Change 'interface ${name}' to 'class ${name}', or call a factory that returns a concrete class instance.`,
|
|
548
|
+
code: "TS2CPP_NEW_ON_INTERFACE",
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
return null;
|
|
553
|
+
}
|
|
554
|
+
if (ts.isDeleteExpression(node)) {
|
|
555
|
+
const target = node.expression;
|
|
556
|
+
let isMapLike = false;
|
|
557
|
+
if (ts.isElementAccessExpression(target)) {
|
|
558
|
+
const objNode = target.expression;
|
|
559
|
+
if (ts.isIdentifier(objNode)) {
|
|
560
|
+
const text = objNode.text;
|
|
561
|
+
if (/^[A-Z]/.test(text) || text === "this") {
|
|
562
|
+
isMapLike = true;
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
if (!isMapLike) {
|
|
567
|
+
return {
|
|
568
|
+
message: "delete on non-map types is unsupported in C++.",
|
|
569
|
+
hint: "Use a Map and its .delete() method, or set the property to null/undefined.",
|
|
570
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
return null;
|
|
574
|
+
}
|
|
575
|
+
if (ts.isCallExpression(node)) {
|
|
576
|
+
const expr = node.expression;
|
|
577
|
+
if (ts.isPropertyAccessExpression(expr)) {
|
|
578
|
+
const methodName = expr.name.text;
|
|
579
|
+
if (ts.isIdentifier(expr.expression) &&
|
|
580
|
+
expr.expression.text === "Object" &&
|
|
581
|
+
(methodName === "keys" || methodName === "values" || methodName === "entries")) {
|
|
582
|
+
if (node.arguments.length > 0) {
|
|
583
|
+
const arg = node.arguments[0];
|
|
584
|
+
let isMapArg = false;
|
|
585
|
+
if (ts.isIdentifier(arg)) {
|
|
586
|
+
const argText = arg.text;
|
|
587
|
+
if (/^[A-Z]/.test(argText) && argText !== "Object") {
|
|
588
|
+
isMapArg = true;
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
if (!isMapArg) {
|
|
592
|
+
return {
|
|
593
|
+
message: `Object.${methodName} on non-map types is unsupported.`,
|
|
594
|
+
hint: "Use a Map and iterate with .keys(), .values(), or .entries() instead.",
|
|
595
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
return null;
|
|
602
|
+
}
|
|
603
|
+
if (ts.isPropertyAccessExpression(node)) {
|
|
604
|
+
const receiver = node.expression;
|
|
605
|
+
const receiverName = ts.isIdentifier(receiver) ? receiver.text : undefined;
|
|
606
|
+
const isCallee = ts.isCallExpression(node.parent) && node.parent.expression === node;
|
|
607
|
+
if (!isCallee) {
|
|
608
|
+
if (receiverName === "Promise" || receiverName === "JSON" || receiverName === "Reflect") {
|
|
609
|
+
return {
|
|
610
|
+
message: `${receiverName}.${node.name.text} depends on JavaScript runtime APIs and has no deterministic C++ lowering.`,
|
|
611
|
+
hint: "Use explicit fixed-shape code instead of runtime reflection or JS runtime helpers.",
|
|
612
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
613
|
+
};
|
|
614
|
+
}
|
|
615
|
+
if (receiverName === "Object" && UNSUPPORTED_OBJECT_RUNTIME_METHODS.has(node.name.text)) {
|
|
616
|
+
return {
|
|
617
|
+
message: `Object.${node.name.text} depends on runtime object-shape behavior and has no deterministic C++ lowering.`,
|
|
618
|
+
hint: "Construct fixed-shape structs explicitly, or use a Map for dynamic data.",
|
|
619
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
if (node.questionDotToken) {
|
|
624
|
+
return {
|
|
625
|
+
message: "Optional chaining (?.) is approximated with a null guard in C++.",
|
|
626
|
+
hint: "The C++ output may behave differently from TypeScript. Use an explicit null check for clarity.",
|
|
627
|
+
code: "TS2CPP_APPROXIMATE",
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
return null;
|
|
631
|
+
}
|
|
632
|
+
if (ts.isBinaryExpression(node)) {
|
|
633
|
+
const opKind = node.operatorToken.kind;
|
|
634
|
+
if (ASSIGNMENT_OPERATOR_KINDS.has(opKind) &&
|
|
635
|
+
ts.isPropertyAccessExpression(node.left) &&
|
|
636
|
+
node.left.name.text === "__proto__") {
|
|
637
|
+
return {
|
|
638
|
+
message: "__proto__ assignment mutates the JavaScript prototype chain and has no AOT C++ lowering.",
|
|
639
|
+
hint: "Use a class with extends, or store dynamic data in a Map.",
|
|
640
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
641
|
+
};
|
|
642
|
+
}
|
|
643
|
+
if (opKind === ts.SyntaxKind.InstanceOfKeyword) {
|
|
644
|
+
return {
|
|
645
|
+
message: "instanceof depends on runtime type metadata and is not deterministic across C++ targets.",
|
|
646
|
+
hint: "Use an explicit discriminator field or enum instead.",
|
|
647
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
if (opKind === ts.SyntaxKind.QuestionQuestionToken) {
|
|
651
|
+
return {
|
|
652
|
+
message: "Nullish coalescing (??) is approximated with a polyfill helper in C++.",
|
|
653
|
+
hint: "Consider using an explicit null check: (x !== null && x !== undefined) ? x : fallback.",
|
|
654
|
+
code: "TS2CPP_APPROXIMATE",
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
if (opKind === ts.SyntaxKind.InKeyword) {
|
|
658
|
+
return {
|
|
659
|
+
message: "The 'in' operator on non-map types is approximated in C++.",
|
|
660
|
+
hint: "Use a Map and its .has() method for reliable membership testing.",
|
|
661
|
+
code: "TS2CPP_APPROXIMATE",
|
|
662
|
+
};
|
|
663
|
+
}
|
|
664
|
+
return null;
|
|
665
|
+
}
|
|
666
|
+
if (node.kind === ts.SyntaxKind.VoidKeyword && node.parent) {
|
|
667
|
+
let current = node.parent;
|
|
668
|
+
while (current) {
|
|
669
|
+
if (ts.isVariableDeclaration(current) ||
|
|
670
|
+
ts.isPropertyDeclaration(current) ||
|
|
671
|
+
ts.isParameter(current) ||
|
|
672
|
+
ts.isBindingElement(current)) {
|
|
673
|
+
return {
|
|
674
|
+
message: "void type annotation on variable/property is erased in C++ (C++ has no void type for variables).",
|
|
675
|
+
hint: "Use 'undefined' or 'null' for optional values, or omit the type annotation.",
|
|
676
|
+
code: "TS2CPP_APPROXIMATE",
|
|
677
|
+
};
|
|
678
|
+
}
|
|
679
|
+
if (ts.isFunctionDeclaration(current) ||
|
|
680
|
+
ts.isMethodDeclaration(current) ||
|
|
681
|
+
ts.isConstructorDeclaration(current) ||
|
|
682
|
+
ts.isGetAccessorDeclaration(current) ||
|
|
683
|
+
ts.isSetAccessorDeclaration(current) ||
|
|
684
|
+
ts.isArrowFunction(current) ||
|
|
685
|
+
ts.isFunctionExpression(current)) {
|
|
686
|
+
return null;
|
|
687
|
+
}
|
|
688
|
+
if (ts.isTypeReferenceNode(current)) {
|
|
689
|
+
return null;
|
|
690
|
+
}
|
|
691
|
+
if (current.parent) {
|
|
692
|
+
current = current.parent;
|
|
693
|
+
}
|
|
694
|
+
else {
|
|
695
|
+
break;
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
return null;
|
|
699
|
+
}
|
|
700
|
+
if (ts.isVoidExpression(node)) {
|
|
701
|
+
return {
|
|
702
|
+
message: "void expression is approximated as (void)(...) in C++.",
|
|
703
|
+
hint: "Avoid using void expressions; they have no practical use in C++ embedded code.",
|
|
704
|
+
code: "TS2CPP_APPROXIMATE",
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
if (node.kind === ts.SyntaxKind.SuperKeyword) {
|
|
708
|
+
// If parent pointers are not available (common with ts.createSourceFile),
|
|
709
|
+
// skip the validation — the transpiler's own super handling (via getActiveExtendsClass)
|
|
710
|
+
// correctly generates base class initializers when super() is valid.
|
|
711
|
+
if (!node.parent) {
|
|
712
|
+
return null;
|
|
713
|
+
}
|
|
714
|
+
let insideExtendingClass = false;
|
|
715
|
+
let current = node.parent;
|
|
716
|
+
while (current) {
|
|
717
|
+
if (ts.isConstructorDeclaration(current) || ts.isMethodDeclaration(current)) {
|
|
718
|
+
const classParent = current.parent;
|
|
719
|
+
if (classParent && ts.isClassDeclaration(classParent) && classParent.heritageClauses) {
|
|
720
|
+
const hasExtends = classParent.heritageClauses.some((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword && clause.types.length > 0);
|
|
721
|
+
if (hasExtends) {
|
|
722
|
+
insideExtendingClass = true;
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
break;
|
|
726
|
+
}
|
|
727
|
+
if (ts.isClassDeclaration(current)) {
|
|
728
|
+
break;
|
|
729
|
+
}
|
|
730
|
+
current = current.parent;
|
|
731
|
+
}
|
|
732
|
+
if (!insideExtendingClass) {
|
|
733
|
+
return {
|
|
734
|
+
message: "super keyword outside of class method context has no valid C++ translation.",
|
|
735
|
+
hint: "Ensure super is only used inside class constructors or methods that have a base class.",
|
|
736
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
737
|
+
};
|
|
738
|
+
}
|
|
739
|
+
return null;
|
|
740
|
+
}
|
|
741
|
+
if (ts.isTypeOfExpression(node)) {
|
|
742
|
+
const inner = node.expression;
|
|
743
|
+
if (!ts.isIdentifier(inner) && !ts.isStringLiteral(inner) && !ts.isNumericLiteral(inner) && inner.kind !== ts.SyntaxKind.TrueKeyword && inner.kind !== ts.SyntaxKind.FalseKeyword) {
|
|
744
|
+
return {
|
|
745
|
+
message: "typeof on non-primitive types returns an approximate type name in C++.",
|
|
746
|
+
hint: "Avoid typeof on objects/arrays; use type guards or instanceof instead.",
|
|
747
|
+
code: "TS2CPP_APPROXIMATE",
|
|
748
|
+
};
|
|
749
|
+
}
|
|
750
|
+
return null;
|
|
751
|
+
}
|
|
752
|
+
if (ts.isTypeReferenceNode(node)) {
|
|
753
|
+
const typeName = node.typeName;
|
|
754
|
+
if (ts.isIdentifier(typeName)) {
|
|
755
|
+
const name = typeName.text;
|
|
756
|
+
if (name === "Promise") {
|
|
757
|
+
return {
|
|
758
|
+
message: "Promise<T> has no deterministic embedded C++ runtime representation.",
|
|
759
|
+
hint: "Use a synchronous result type or an explicit callback interface instead.",
|
|
760
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
761
|
+
};
|
|
762
|
+
}
|
|
763
|
+
if (UNSUPPORTED_RUNTIME_GLOBALS.has(name)) {
|
|
764
|
+
return {
|
|
765
|
+
message: `${name} has no deterministic AOT C++ representation.`,
|
|
766
|
+
hint: "Use ordinary classes, structs, functions, or values instead.",
|
|
767
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
768
|
+
};
|
|
769
|
+
}
|
|
770
|
+
const erasedUtilityTypes = new Set(["Partial", "Required", "Readonly", "Pick", "Omit"]);
|
|
771
|
+
if (erasedUtilityTypes.has(name)) {
|
|
772
|
+
return {
|
|
773
|
+
status: "approximation",
|
|
774
|
+
message: `TypeScript utility type '${name}<...>' is erased to its base type during transpilation.`,
|
|
775
|
+
hint: `Define an explicit interface or struct if you need ${name}'s TypeScript semantics.`,
|
|
776
|
+
code: "TS2CPP_APPROXIMATE",
|
|
777
|
+
};
|
|
778
|
+
}
|
|
779
|
+
const autoUtilityTypes = new Set(["Exclude", "Extract", "ReturnType", "InstanceType", "Parameters", "ConstructorParameters"]);
|
|
780
|
+
if (autoUtilityTypes.has(name)) {
|
|
781
|
+
return {
|
|
782
|
+
message: `TypeScript utility type '${name}<...>' falls back to 'auto' and is not deterministic enough for C++ emission.`,
|
|
783
|
+
hint: `Define the concrete type explicitly instead of using ${name}.`,
|
|
784
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
785
|
+
};
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
return null;
|
|
789
|
+
}
|
|
790
|
+
if (ts.isTypeOperatorNode(node)) {
|
|
791
|
+
if (node.operator === ts.SyntaxKind.KeyOfKeyword) {
|
|
792
|
+
return {
|
|
793
|
+
message: "The 'keyof' type operator has no C++ equivalent.",
|
|
794
|
+
hint: "Use an enum or string literal union to represent key sets explicitly.",
|
|
795
|
+
code: "TS2CPP_NO_EQUIVALENT",
|
|
796
|
+
};
|
|
797
|
+
}
|
|
798
|
+
return null;
|
|
799
|
+
}
|
|
800
|
+
if (ts.isAsExpression(node)) {
|
|
801
|
+
return {
|
|
802
|
+
message: "Type assertion ('as') is a type-only construct with no runtime effect in C++.",
|
|
803
|
+
hint: "Remove 'as' casts or replace with explicit conversion functions.",
|
|
804
|
+
code: "TS2CPP_APPROXIMATE",
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
if (ts.isEnumDeclaration(node)) {
|
|
808
|
+
// String-valued enums ARE supported: type-decl-emitter.ts lowers them to a
|
|
809
|
+
// `namespace EnumName { constexpr const char* Member = "..."; }` so member
|
|
810
|
+
// access yields a `const char*` and `===` / concatenation behave like TS
|
|
811
|
+
// (see isStringEnum). The historical "no C++ equivalent" warning here was
|
|
812
|
+
// stale and contradicted the working lowering — removed (demo #14 F).
|
|
813
|
+
return null;
|
|
814
|
+
}
|
|
815
|
+
return null;
|
|
816
|
+
}
|