tsc-ts 0.0.4 → 0.0.6
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/README.md +34 -2
- package/dist/api/compiler/ast-utilities.d.ts +82 -0
- package/dist/api/compiler/ast-utilities.js +462 -0
- package/dist/api/compiler/ast.d.ts +2351 -0
- package/dist/api/compiler/ast.js +11212 -0
- package/dist/api/compiler/astnav.d.ts +37 -0
- package/dist/api/compiler/astnav.js +767 -0
- package/dist/api/compiler/binder-utilities.d.ts +182 -0
- package/dist/api/compiler/binder-utilities.js +1241 -0
- package/dist/api/compiler/binder.d.ts +33 -0
- package/dist/api/compiler/binder.js +2359 -0
- package/dist/api/compiler/character-codes.d.ts +161 -0
- package/dist/api/compiler/character-codes.js +160 -0
- package/dist/api/compiler/checker-calls.d.ts +46 -0
- package/dist/api/compiler/checker-calls.js +1641 -0
- package/dist/api/compiler/checker-classes.d.ts +30 -0
- package/dist/api/compiler/checker-classes.js +582 -0
- package/dist/api/compiler/checker-contextual.d.ts +77 -0
- package/dist/api/compiler/checker-contextual.js +1136 -0
- package/dist/api/compiler/checker-declaration-order.d.ts +12 -0
- package/dist/api/compiler/checker-declaration-order.js +357 -0
- package/dist/api/compiler/checker-declarations.d.ts +33 -0
- package/dist/api/compiler/checker-declarations.js +888 -0
- package/dist/api/compiler/checker-declared-types.d.ts +48 -0
- package/dist/api/compiler/checker-declared-types.js +788 -0
- package/dist/api/compiler/checker-decorators.d.ts +26 -0
- package/dist/api/compiler/checker-decorators.js +562 -0
- package/dist/api/compiler/checker-deprecation.d.ts +33 -0
- package/dist/api/compiler/checker-deprecation.js +314 -0
- package/dist/api/compiler/checker-destructuring.d.ts +34 -0
- package/dist/api/compiler/checker-destructuring.js +584 -0
- package/dist/api/compiler/checker-elaboration.d.ts +15 -0
- package/dist/api/compiler/checker-elaboration.js +291 -0
- package/dist/api/compiler/checker-emit-helpers.d.ts +58 -0
- package/dist/api/compiler/checker-emit-helpers.js +154 -0
- package/dist/api/compiler/checker-emit-resolver.d.ts +75 -0
- package/dist/api/compiler/checker-emit-resolver.js +580 -0
- package/dist/api/compiler/checker-evaluator.d.ts +27 -0
- package/dist/api/compiler/checker-evaluator.js +188 -0
- package/dist/api/compiler/checker-expressions.d.ts +67 -0
- package/dist/api/compiler/checker-expressions.js +1351 -0
- package/dist/api/compiler/checker-features.d.ts +6 -0
- package/dist/api/compiler/checker-features.js +354 -0
- package/dist/api/compiler/checker-flow.d.ts +86 -0
- package/dist/api/compiler/checker-flow.js +169 -0
- package/dist/api/compiler/checker-functions.d.ts +43 -0
- package/dist/api/compiler/checker-functions.js +1002 -0
- package/dist/api/compiler/checker-generated-code.d.ts +25 -0
- package/dist/api/compiler/checker-generated-code.js +168 -0
- package/dist/api/compiler/checker-globals.d.ts +14 -0
- package/dist/api/compiler/checker-globals.js +37 -0
- package/dist/api/compiler/checker-grammar.d.ts +35 -0
- package/dist/api/compiler/checker-grammar.js +2587 -0
- package/dist/api/compiler/checker-heritage.d.ts +28 -0
- package/dist/api/compiler/checker-heritage.js +901 -0
- package/dist/api/compiler/checker-inference.d.ts +179 -0
- package/dist/api/compiler/checker-inference.js +2105 -0
- package/dist/api/compiler/checker-iteration.d.ts +115 -0
- package/dist/api/compiler/checker-iteration.js +857 -0
- package/dist/api/compiler/checker-javascript.d.ts +42 -0
- package/dist/api/compiler/checker-javascript.js +442 -0
- package/dist/api/compiler/checker-jsdoc.d.ts +30 -0
- package/dist/api/compiler/checker-jsdoc.js +320 -0
- package/dist/api/compiler/checker-jsx.d.ts +94 -0
- package/dist/api/compiler/checker-jsx.js +1433 -0
- package/dist/api/compiler/checker-literals.d.ts +6 -0
- package/dist/api/compiler/checker-literals.js +43 -0
- package/dist/api/compiler/checker-members.d.ts +200 -0
- package/dist/api/compiler/checker-members.js +2148 -0
- package/dist/api/compiler/checker-modules.d.ts +85 -0
- package/dist/api/compiler/checker-modules.js +2141 -0
- package/dist/api/compiler/checker-narrowing.d.ts +120 -0
- package/dist/api/compiler/checker-narrowing.js +2797 -0
- package/dist/api/compiler/checker-object-literals.d.ts +14 -0
- package/dist/api/compiler/checker-object-literals.js +483 -0
- package/dist/api/compiler/checker-operators.d.ts +33 -0
- package/dist/api/compiler/checker-operators.js +1040 -0
- package/dist/api/compiler/checker-overloads.d.ts +7 -0
- package/dist/api/compiler/checker-overloads.js +271 -0
- package/dist/api/compiler/checker-property-access.d.ts +34 -0
- package/dist/api/compiler/checker-property-access.js +672 -0
- package/dist/api/compiler/checker-services.d.ts +49 -0
- package/dist/api/compiler/checker-services.js +995 -0
- package/dist/api/compiler/checker-signatures.d.ts +55 -0
- package/dist/api/compiler/checker-signatures.js +789 -0
- package/dist/api/compiler/checker-source-file.d.ts +27 -0
- package/dist/api/compiler/checker-source-file.js +619 -0
- package/dist/api/compiler/checker-statements.d.ts +18 -0
- package/dist/api/compiler/checker-statements.js +226 -0
- package/dist/api/compiler/checker-super.d.ts +13 -0
- package/dist/api/compiler/checker-super.js +241 -0
- package/dist/api/compiler/checker-symbol-types.d.ts +51 -0
- package/dist/api/compiler/checker-symbol-types.js +955 -0
- package/dist/api/compiler/checker-symbols.d.ts +181 -0
- package/dist/api/compiler/checker-symbols.js +1784 -0
- package/dist/api/compiler/checker-type-factory.d.ts +142 -0
- package/dist/api/compiler/checker-type-factory.js +2542 -0
- package/dist/api/compiler/checker-type-nodes.d.ts +26 -0
- package/dist/api/compiler/checker-type-nodes.js +828 -0
- package/dist/api/compiler/checker-type-operators.d.ts +109 -0
- package/dist/api/compiler/checker-type-operators.js +1842 -0
- package/dist/api/compiler/checker-types.d.ts +1093 -0
- package/dist/api/compiler/checker-types.js +1874 -0
- package/dist/api/compiler/checker-unused.d.ts +19 -0
- package/dist/api/compiler/checker-unused.js +524 -0
- package/dist/api/compiler/checker-utilities.d.ts +33 -0
- package/dist/api/compiler/checker-utilities.js +141 -0
- package/dist/api/compiler/checker.d.ts +512 -0
- package/dist/api/compiler/checker.js +932 -0
- package/dist/api/compiler/command-line.d.ts +32 -0
- package/dist/api/compiler/command-line.js +383 -0
- package/dist/api/compiler/compile-program.d.ts +118 -0
- package/dist/api/compiler/compile-program.js +384 -0
- package/dist/api/compiler/diagnostic-locales.d.ts +22 -0
- package/dist/api/compiler/diagnostic-locales.js +64 -0
- package/dist/api/compiler/diagnostic-messages.d.ts +2166 -0
- package/dist/api/compiler/diagnostic-messages.js +184 -0
- package/dist/api/compiler/diagnostics.d.ts +161 -0
- package/dist/api/compiler/diagnostics.js +784 -0
- package/dist/api/compiler/emitter.d.ts +71 -0
- package/dist/api/compiler/emitter.js +327 -0
- package/dist/api/compiler/file-include.d.ts +144 -0
- package/dist/api/compiler/file-include.js +599 -0
- package/dist/api/compiler/file-loader.d.ts +290 -0
- package/dist/api/compiler/file-loader.js +1323 -0
- package/dist/api/compiler/file-system.d.ts +51 -0
- package/dist/api/compiler/file-system.js +132 -0
- package/dist/api/compiler/flow.d.ts +60 -0
- package/dist/api/compiler/flow.js +45 -0
- package/dist/api/compiler/instantiation.d.ts +74 -0
- package/dist/api/compiler/instantiation.js +835 -0
- package/dist/api/compiler/jsdoc.d.ts +75 -0
- package/dist/api/compiler/jsdoc.js +1229 -0
- package/dist/api/compiler/link-tables.d.ts +105 -0
- package/dist/api/compiler/link-tables.js +319 -0
- package/dist/api/compiler/locale-data.d.ts +24 -0
- package/dist/api/compiler/locale-data.js +183 -0
- package/dist/api/compiler/locale.d.ts +4 -0
- package/dist/api/compiler/locale.js +317 -0
- package/dist/api/compiler/locales/cs-CZ.d.ts +2 -0
- package/dist/api/compiler/locales/cs-CZ.js +3 -0
- package/dist/api/compiler/locales/de-DE.d.ts +2 -0
- package/dist/api/compiler/locales/de-DE.js +3 -0
- package/dist/api/compiler/locales/es-ES.d.ts +2 -0
- package/dist/api/compiler/locales/es-ES.js +3 -0
- package/dist/api/compiler/locales/fr-FR.d.ts +2 -0
- package/dist/api/compiler/locales/fr-FR.js +3 -0
- package/dist/api/compiler/locales/it-IT.d.ts +2 -0
- package/dist/api/compiler/locales/it-IT.js +3 -0
- package/dist/api/compiler/locales/ja-JP.d.ts +2 -0
- package/dist/api/compiler/locales/ja-JP.js +3 -0
- package/dist/api/compiler/locales/ko-KR.d.ts +2 -0
- package/dist/api/compiler/locales/ko-KR.js +3 -0
- package/dist/api/compiler/locales/pl-PL.d.ts +2 -0
- package/dist/api/compiler/locales/pl-PL.js +3 -0
- package/dist/api/compiler/locales/pt-BR.d.ts +2 -0
- package/dist/api/compiler/locales/pt-BR.js +3 -0
- package/dist/api/compiler/locales/ru-RU.d.ts +2 -0
- package/dist/api/compiler/locales/ru-RU.js +3 -0
- package/dist/api/compiler/locales/tr-TR.d.ts +2 -0
- package/dist/api/compiler/locales/tr-TR.js +3 -0
- package/dist/api/compiler/locales/zh-CN.d.ts +2 -0
- package/dist/api/compiler/locales/zh-CN.js +3 -0
- package/dist/api/compiler/locales/zh-TW.d.ts +2 -0
- package/dist/api/compiler/locales/zh-TW.js +3 -0
- package/dist/api/compiler/module-resolution-types.d.ts +83 -0
- package/dist/api/compiler/module-resolution-types.js +176 -0
- package/dist/api/compiler/module-resolution.d.ts +71 -0
- package/dist/api/compiler/module-resolution.js +1598 -0
- package/dist/api/compiler/module-specifiers.d.ts +64 -0
- package/dist/api/compiler/module-specifiers.js +1101 -0
- package/dist/api/compiler/name-resolver.d.ts +43 -0
- package/dist/api/compiler/name-resolver.js +509 -0
- package/dist/api/compiler/node-builder-names.d.ts +32 -0
- package/dist/api/compiler/node-builder-names.js +854 -0
- package/dist/api/compiler/node-builder-pseudo.d.ts +36 -0
- package/dist/api/compiler/node-builder-pseudo.js +745 -0
- package/dist/api/compiler/node-builder-reuse.d.ts +4 -0
- package/dist/api/compiler/node-builder-reuse.js +647 -0
- package/dist/api/compiler/node-builder.d.ts +270 -0
- package/dist/api/compiler/node-builder.js +2645 -0
- package/dist/api/compiler/option-declarations.d.ts +90 -0
- package/dist/api/compiler/option-declarations.js +1460 -0
- package/dist/api/compiler/options.d.ts +289 -0
- package/dist/api/compiler/options.js +1197 -0
- package/dist/api/compiler/output-paths.d.ts +42 -0
- package/dist/api/compiler/output-paths.js +195 -0
- package/dist/api/compiler/package-json.d.ts +175 -0
- package/dist/api/compiler/package-json.js +1015 -0
- package/dist/api/compiler/parallel-parse.d.ts +221 -0
- package/dist/api/compiler/parallel-parse.js +541 -0
- package/dist/api/compiler/parser.d.ts +604 -0
- package/dist/api/compiler/parser.js +6426 -0
- package/dist/api/compiler/path.d.ts +91 -0
- package/dist/api/compiler/path.js +705 -0
- package/dist/api/compiler/printer/async-helpers.d.ts +22 -0
- package/dist/api/compiler/printer/async-helpers.js +91 -0
- package/dist/api/compiler/printer/auto-generate.d.ts +13 -0
- package/dist/api/compiler/printer/auto-generate.js +20 -0
- package/dist/api/compiler/printer/decorator-helpers.d.ts +24 -0
- package/dist/api/compiler/printer/decorator-helpers.js +118 -0
- package/dist/api/compiler/printer/emit-context.d.ts +157 -0
- package/dist/api/compiler/printer/emit-context.js +582 -0
- package/dist/api/compiler/printer/emit-flags.d.ts +60 -0
- package/dist/api/compiler/printer/emit-flags.js +2 -0
- package/dist/api/compiler/printer/factory-base.d.ts +171 -0
- package/dist/api/compiler/printer/factory-base.js +1505 -0
- package/dist/api/compiler/printer/factory.d.ts +147 -0
- package/dist/api/compiler/printer/factory.js +542 -0
- package/dist/api/compiler/printer/helpers.d.ts +27 -0
- package/dist/api/compiler/printer/helpers.js +164 -0
- package/dist/api/compiler/printer/name-generator.d.ts +41 -0
- package/dist/api/compiler/printer/name-generator.js +283 -0
- package/dist/api/compiler/printer/printer.d.ts +411 -0
- package/dist/api/compiler/printer/printer.js +4517 -0
- package/dist/api/compiler/printer/text-writer.d.ts +46 -0
- package/dist/api/compiler/printer/text-writer.js +172 -0
- package/dist/api/compiler/printer/utilities.d.ts +82 -0
- package/dist/api/compiler/printer/utilities.js +817 -0
- package/dist/api/compiler/program-checker.d.ts +156 -0
- package/dist/api/compiler/program-checker.js +529 -0
- package/dist/api/compiler/program-utilities.d.ts +52 -0
- package/dist/api/compiler/program-utilities.js +365 -0
- package/dist/api/compiler/program.d.ts +180 -0
- package/dist/api/compiler/program.js +1019 -0
- package/dist/api/compiler/pseudo-bigint.d.ts +5 -0
- package/dist/api/compiler/pseudo-bigint.js +61 -0
- package/dist/api/compiler/regexp-checker.d.ts +38 -0
- package/dist/api/compiler/regexp-checker.js +942 -0
- package/dist/api/compiler/relations.d.ts +263 -0
- package/dist/api/compiler/relations.js +4002 -0
- package/dist/api/compiler/reparser.d.ts +48 -0
- package/dist/api/compiler/reparser.js +1323 -0
- package/dist/api/compiler/scanner.d.ts +256 -0
- package/dist/api/compiler/scanner.js +2853 -0
- package/dist/api/compiler/side-state.d.ts +16 -0
- package/dist/api/compiler/side-state.js +89 -0
- package/dist/api/compiler/sourcemap.d.ts +55 -0
- package/dist/api/compiler/sourcemap.js +340 -0
- package/dist/api/compiler/spelling.d.ts +14 -0
- package/dist/api/compiler/spelling.js +128 -0
- package/dist/api/compiler/symbol-accessibility.d.ts +57 -0
- package/dist/api/compiler/symbol-accessibility.js +991 -0
- package/dist/api/compiler/symbol.d.ts +282 -0
- package/dist/api/compiler/symbol.js +339 -0
- package/dist/api/compiler/symlinks.d.ts +32 -0
- package/dist/api/compiler/symlinks.js +114 -0
- package/dist/api/compiler/syntax-kind.d.ts +389 -0
- package/dist/api/compiler/syntax-kind.js +2 -0
- package/dist/api/compiler/timeline.d.ts +9 -0
- package/dist/api/compiler/timeline.js +54 -0
- package/dist/api/compiler/transformers/alias-references.d.ts +39 -0
- package/dist/api/compiler/transformers/alias-references.js +677 -0
- package/dist/api/compiler/transformers/async-utilities.d.ts +51 -0
- package/dist/api/compiler/transformers/async-utilities.js +260 -0
- package/dist/api/compiler/transformers/async.d.ts +53 -0
- package/dist/api/compiler/transformers/async.js +645 -0
- package/dist/api/compiler/transformers/class-fields.d.ts +206 -0
- package/dist/api/compiler/transformers/class-fields.js +2418 -0
- package/dist/api/compiler/transformers/class-utilities.d.ts +46 -0
- package/dist/api/compiler/transformers/class-utilities.js +261 -0
- package/dist/api/compiler/transformers/commonjs-module.d.ts +103 -0
- package/dist/api/compiler/transformers/commonjs-module.js +1180 -0
- package/dist/api/compiler/transformers/const-enum-inliner.d.ts +11 -0
- package/dist/api/compiler/transformers/const-enum-inliner.js +36 -0
- package/dist/api/compiler/transformers/declarations-diagnostics.d.ts +52 -0
- package/dist/api/compiler/transformers/declarations-diagnostics.js +539 -0
- package/dist/api/compiler/transformers/declarations-pseudo.d.ts +160 -0
- package/dist/api/compiler/transformers/declarations-pseudo.js +799 -0
- package/dist/api/compiler/transformers/declarations-resolver.d.ts +152 -0
- package/dist/api/compiler/transformers/declarations-resolver.js +35 -0
- package/dist/api/compiler/transformers/declarations-syntactic.d.ts +119 -0
- package/dist/api/compiler/transformers/declarations-syntactic.js +1582 -0
- package/dist/api/compiler/transformers/declarations-tracker.d.ts +46 -0
- package/dist/api/compiler/transformers/declarations-tracker.js +198 -0
- package/dist/api/compiler/transformers/declarations.d.ts +175 -0
- package/dist/api/compiler/transformers/declarations.js +2381 -0
- package/dist/api/compiler/transformers/decorator-metadata.d.ts +54 -0
- package/dist/api/compiler/transformers/decorator-metadata.js +554 -0
- package/dist/api/compiler/transformers/decorator-utilities.d.ts +38 -0
- package/dist/api/compiler/transformers/decorator-utilities.js +238 -0
- package/dist/api/compiler/transformers/destructuring.d.ts +25 -0
- package/dist/api/compiler/transformers/destructuring.js +626 -0
- package/dist/api/compiler/transformers/downlevel.d.ts +6 -0
- package/dist/api/compiler/transformers/downlevel.js +45 -0
- package/dist/api/compiler/transformers/emit-resolver.d.ts +61 -0
- package/dist/api/compiler/transformers/emit-resolver.js +197 -0
- package/dist/api/compiler/transformers/es-decorators.d.ts +118 -0
- package/dist/api/compiler/transformers/es-decorators.js +1901 -0
- package/dist/api/compiler/transformers/exponentiation.d.ts +11 -0
- package/dist/api/compiler/transformers/exponentiation.js +76 -0
- package/dist/api/compiler/transformers/external-module-info.d.ts +35 -0
- package/dist/api/compiler/transformers/external-module-info.js +351 -0
- package/dist/api/compiler/transformers/for-await.d.ts +43 -0
- package/dist/api/compiler/transformers/for-await.js +469 -0
- package/dist/api/compiler/transformers/import-elision.d.ts +16 -0
- package/dist/api/compiler/transformers/import-elision.js +124 -0
- package/dist/api/compiler/transformers/jsx-entities.d.ts +1 -0
- package/dist/api/compiler/transformers/jsx-entities.js +256 -0
- package/dist/api/compiler/transformers/jsx.d.ts +71 -0
- package/dist/api/compiler/transformers/jsx.js +700 -0
- package/dist/api/compiler/transformers/legacy-decorators.d.ts +56 -0
- package/dist/api/compiler/transformers/legacy-decorators.js +564 -0
- package/dist/api/compiler/transformers/logical-assignment.d.ts +14 -0
- package/dist/api/compiler/transformers/logical-assignment.js +62 -0
- package/dist/api/compiler/transformers/module-utilities.d.ts +9 -0
- package/dist/api/compiler/transformers/module-utilities.js +36 -0
- package/dist/api/compiler/transformers/module.d.ts +49 -0
- package/dist/api/compiler/transformers/module.js +296 -0
- package/dist/api/compiler/transformers/named-evaluation.d.ts +26 -0
- package/dist/api/compiler/transformers/named-evaluation.js +266 -0
- package/dist/api/compiler/transformers/nullish-coalescing.d.ts +9 -0
- package/dist/api/compiler/transformers/nullish-coalescing.js +26 -0
- package/dist/api/compiler/transformers/object-rest-spread.d.ts +34 -0
- package/dist/api/compiler/transformers/object-rest-spread.js +411 -0
- package/dist/api/compiler/transformers/optional-catch.d.ts +9 -0
- package/dist/api/compiler/transformers/optional-catch.js +20 -0
- package/dist/api/compiler/transformers/optional-chain.d.ts +14 -0
- package/dist/api/compiler/transformers/optional-chain.js +188 -0
- package/dist/api/compiler/transformers/reference-resolver.d.ts +129 -0
- package/dist/api/compiler/transformers/reference-resolver.js +1157 -0
- package/dist/api/compiler/transformers/runtime-syntax.d.ts +71 -0
- package/dist/api/compiler/transformers/runtime-syntax.js +753 -0
- package/dist/api/compiler/transformers/subtree-facts.d.ts +10 -0
- package/dist/api/compiler/transformers/subtree-facts.js +205 -0
- package/dist/api/compiler/transformers/syntax-facts.d.ts +52 -0
- package/dist/api/compiler/transformers/syntax-facts.js +258 -0
- package/dist/api/compiler/transformers/tagged-template.d.ts +17 -0
- package/dist/api/compiler/transformers/tagged-template.js +148 -0
- package/dist/api/compiler/transformers/transformer.d.ts +17 -0
- package/dist/api/compiler/transformers/transformer.js +54 -0
- package/dist/api/compiler/transformers/type-eraser.d.ts +21 -0
- package/dist/api/compiler/transformers/type-eraser.js +346 -0
- package/dist/api/compiler/transformers/type-serialization.d.ts +20 -0
- package/dist/api/compiler/transformers/type-serialization.js +347 -0
- package/dist/api/compiler/transformers/using.d.ts +56 -0
- package/dist/api/compiler/transformers/using.js +453 -0
- package/dist/api/compiler/transformers/utilities.d.ts +50 -0
- package/dist/api/compiler/transformers/utilities.js +347 -0
- package/dist/api/compiler/transformers/visitor-base.d.ts +6 -0
- package/dist/api/compiler/transformers/visitor-base.js +817 -0
- package/dist/api/compiler/transformers/visitor-hooks.d.ts +29 -0
- package/dist/api/compiler/transformers/visitor-hooks.js +189 -0
- package/dist/api/compiler/tsconfig.d.ts +177 -0
- package/dist/api/compiler/tsconfig.js +1311 -0
- package/dist/api/compiler/type-printer.d.ts +15 -0
- package/dist/api/compiler/type-printer.js +74 -0
- package/dist/api/compiler/types.d.ts +87 -0
- package/dist/api/compiler/types.js +23 -0
- package/dist/api/compiler/unicode-identifiers.d.ts +2 -0
- package/dist/api/compiler/unicode-identifiers.js +209 -0
- package/dist/api/compiler/unicode-properties.d.ts +8 -0
- package/dist/api/compiler/unicode-properties.js +531 -0
- package/dist/api/compiler/vfs-match.d.ts +24 -0
- package/dist/api/compiler/vfs-match.js +587 -0
- package/dist/api/library/ast.d.ts +3 -2
- package/dist/api/library/ast.generated.d.ts +127 -139
- package/dist/api/library/checker.d.ts +51 -0
- package/dist/api/library/checker.js +318 -0
- package/dist/api/library/diagnostics.d.ts +13 -0
- package/dist/api/library/diagnostics.js +50 -0
- package/dist/api/library/disk.d.ts +13 -0
- package/dist/api/library/disk.js +66 -0
- package/dist/api/library/errors.d.ts +13 -0
- package/dist/api/library/errors.js +24 -0
- package/dist/api/library/host.d.ts +24 -0
- package/dist/api/library/host.js +52 -0
- package/dist/api/library/index.d.ts +5 -1
- package/dist/api/library/index.js +4 -0
- package/dist/api/library/nodes.d.ts +51 -0
- package/dist/api/library/nodes.js +196 -0
- package/dist/api/library/options.d.ts +144 -0
- package/dist/api/library/options.js +308 -0
- package/dist/api/library/parse.d.ts +19 -0
- package/dist/api/library/parse.js +41 -0
- package/dist/api/library/program.d.ts +21 -0
- package/dist/api/library/program.js +234 -0
- package/dist/api/library/types.d.ts +14 -1
- package/package.json +12 -8
- package/src/compiler/ast-utilities.ts +548 -0
- package/src/compiler/ast.ts +12870 -0
- package/src/compiler/astnav.ts +799 -0
- package/src/compiler/binder-utilities.ts +1392 -0
- package/src/compiler/binder.ts +2707 -0
- package/src/compiler/build-info.ts +1197 -0
- package/src/compiler/character-codes.ts +323 -0
- package/src/compiler/checker-calls.ts +2155 -0
- package/src/compiler/checker-classes.ts +706 -0
- package/src/compiler/checker-contextual.ts +1457 -0
- package/src/compiler/checker-declaration-order.ts +438 -0
- package/src/compiler/checker-declarations.ts +1201 -0
- package/src/compiler/checker-declared-types.ts +919 -0
- package/src/compiler/checker-decorators.ts +694 -0
- package/src/compiler/checker-deprecation.ts +355 -0
- package/src/compiler/checker-destructuring.ts +805 -0
- package/src/compiler/checker-elaboration.ts +477 -0
- package/src/compiler/checker-emit-helpers.ts +224 -0
- package/src/compiler/checker-emit-resolver.ts +769 -0
- package/src/compiler/checker-evaluator.ts +243 -0
- package/src/compiler/checker-expressions.ts +1831 -0
- package/src/compiler/checker-features.ts +361 -0
- package/src/compiler/checker-flow.ts +394 -0
- package/src/compiler/checker-functions.ts +1296 -0
- package/src/compiler/checker-generated-code.ts +227 -0
- package/src/compiler/checker-globals.ts +52 -0
- package/src/compiler/checker-grammar.ts +3596 -0
- package/src/compiler/checker-heritage.ts +1240 -0
- package/src/compiler/checker-inference.ts +2584 -0
- package/src/compiler/checker-iteration.ts +1206 -0
- package/src/compiler/checker-javascript.ts +502 -0
- package/src/compiler/checker-jsdoc.ts +360 -0
- package/src/compiler/checker-jsx.ts +1928 -0
- package/src/compiler/checker-literals.ts +61 -0
- package/src/compiler/checker-members.ts +2480 -0
- package/src/compiler/checker-modules.ts +2896 -0
- package/src/compiler/checker-narrowing.ts +3230 -0
- package/src/compiler/checker-object-literals.ts +591 -0
- package/src/compiler/checker-operators.ts +1422 -0
- package/src/compiler/checker-overloads.ts +328 -0
- package/src/compiler/checker-property-access.ts +906 -0
- package/src/compiler/checker-services.ts +1149 -0
- package/src/compiler/checker-signatures.ts +1032 -0
- package/src/compiler/checker-source-file.ts +732 -0
- package/src/compiler/checker-statements.ts +292 -0
- package/src/compiler/checker-super.ts +261 -0
- package/src/compiler/checker-symbol-types.ts +1187 -0
- package/src/compiler/checker-symbols.ts +2157 -0
- package/src/compiler/checker-type-factory.ts +2616 -0
- package/src/compiler/checker-type-nodes.ts +1033 -0
- package/src/compiler/checker-type-operators.ts +2510 -0
- package/src/compiler/checker-types.ts +2520 -0
- package/src/compiler/checker-unused.ts +642 -0
- package/src/compiler/checker-utilities.ts +161 -0
- package/src/compiler/checker.ts +1138 -0
- package/src/compiler/command-line.ts +436 -0
- package/src/compiler/compile-program.ts +439 -0
- package/src/compiler/decoder.ts +1209 -0
- package/src/compiler/diagnostic-locales.ts +86 -0
- package/src/compiler/diagnostic-messages.ts +2349 -0
- package/src/compiler/diagnostics.ts +858 -0
- package/src/compiler/emitter.ts +434 -0
- package/src/compiler/encoder.ts +1945 -0
- package/src/compiler/file-include.ts +741 -0
- package/src/compiler/file-loader.ts +1597 -0
- package/src/compiler/file-system.ts +143 -0
- package/src/compiler/flow.ts +89 -0
- package/src/compiler/help.ts +473 -0
- package/src/compiler/incremental.ts +2818 -0
- package/src/compiler/init.ts +141 -0
- package/src/compiler/instantiation.ts +938 -0
- package/src/compiler/jsdoc.ts +1386 -0
- package/src/compiler/link-tables.ts +343 -0
- package/src/compiler/locale-data.ts +203 -0
- package/src/compiler/locale.ts +307 -0
- package/src/compiler/locales/cs-CZ.ts +5 -0
- package/src/compiler/locales/de-DE.ts +5 -0
- package/src/compiler/locales/es-ES.ts +5 -0
- package/src/compiler/locales/fr-FR.ts +5 -0
- package/src/compiler/locales/it-IT.ts +5 -0
- package/src/compiler/locales/ja-JP.ts +5 -0
- package/src/compiler/locales/ko-KR.ts +5 -0
- package/src/compiler/locales/pl-PL.ts +5 -0
- package/src/compiler/locales/pt-BR.ts +5 -0
- package/src/compiler/locales/ru-RU.ts +5 -0
- package/src/compiler/locales/tr-TR.ts +5 -0
- package/src/compiler/locales/zh-CN.ts +5 -0
- package/src/compiler/locales/zh-TW.ts +5 -0
- package/src/compiler/module-resolution-types.ts +243 -0
- package/src/compiler/module-resolution.ts +2072 -0
- package/src/compiler/module-specifiers.ts +1491 -0
- package/src/compiler/name-resolver.ts +646 -0
- package/src/compiler/node-builder-names.ts +1071 -0
- package/src/compiler/node-builder-pseudo.ts +892 -0
- package/src/compiler/node-builder-reuse.ts +764 -0
- package/src/compiler/node-builder.ts +3433 -0
- package/src/compiler/option-declarations.ts +1560 -0
- package/src/compiler/options.ts +1576 -0
- package/src/compiler/output-paths.ts +334 -0
- package/src/compiler/package-json.ts +1083 -0
- package/src/compiler/parallel-check.ts +1954 -0
- package/src/compiler/parallel-parse.ts +595 -0
- package/src/compiler/parse-thread.ts +136 -0
- package/src/compiler/parser.ts +7766 -0
- package/src/compiler/path.ts +717 -0
- package/src/compiler/printer/async-helpers.ts +183 -0
- package/src/compiler/printer/auto-generate.ts +27 -0
- package/src/compiler/printer/decorator-helpers.ts +218 -0
- package/src/compiler/printer/emit-context.ts +684 -0
- package/src/compiler/printer/emit-flags.ts +64 -0
- package/src/compiler/printer/factory-base.ts +2577 -0
- package/src/compiler/printer/factory.ts +764 -0
- package/src/compiler/printer/helpers.ts +291 -0
- package/src/compiler/printer/name-generator.ts +372 -0
- package/src/compiler/printer/printer.ts +5072 -0
- package/src/compiler/printer/text-writer.ts +183 -0
- package/src/compiler/printer/utilities.ts +884 -0
- package/src/compiler/program-checker.ts +594 -0
- package/src/compiler/program-utilities.ts +435 -0
- package/src/compiler/program.ts +1426 -0
- package/src/compiler/pseudo-bigint.ts +62 -0
- package/src/compiler/regexp-checker.ts +1142 -0
- package/src/compiler/relations.ts +5149 -0
- package/src/compiler/reparser.ts +1566 -0
- package/src/compiler/scanner.ts +2951 -0
- package/src/compiler/show-config.ts +239 -0
- package/src/compiler/side-state.ts +125 -0
- package/src/compiler/sourcemap.ts +366 -0
- package/src/compiler/spelling.ts +122 -0
- package/src/compiler/symbol-accessibility.ts +1166 -0
- package/src/compiler/symbol.ts +557 -0
- package/src/compiler/symlinks.ts +137 -0
- package/src/compiler/syntax-kind.ts +391 -0
- package/src/compiler/thread-entry.ts +191 -0
- package/src/compiler/timeline.ts +53 -0
- package/src/compiler/transformers/alias-references.ts +757 -0
- package/src/compiler/transformers/async-utilities.ts +335 -0
- package/src/compiler/transformers/async.ts +838 -0
- package/src/compiler/transformers/class-fields.ts +2967 -0
- package/src/compiler/transformers/class-utilities.ts +324 -0
- package/src/compiler/transformers/commonjs-module.ts +1621 -0
- package/src/compiler/transformers/const-enum-inliner.ts +50 -0
- package/src/compiler/transformers/declarations-diagnostics.ts +833 -0
- package/src/compiler/transformers/declarations-pseudo.ts +969 -0
- package/src/compiler/transformers/declarations-resolver.ts +249 -0
- package/src/compiler/transformers/declarations-syntactic.ts +1867 -0
- package/src/compiler/transformers/declarations-tracker.ts +269 -0
- package/src/compiler/transformers/declarations.ts +3120 -0
- package/src/compiler/transformers/decorator-metadata.ts +697 -0
- package/src/compiler/transformers/decorator-utilities.ts +283 -0
- package/src/compiler/transformers/destructuring.ts +708 -0
- package/src/compiler/transformers/downlevel.ts +50 -0
- package/src/compiler/transformers/emit-resolver.ts +258 -0
- package/src/compiler/transformers/es-decorators.ts +2682 -0
- package/src/compiler/transformers/exponentiation.ts +80 -0
- package/src/compiler/transformers/external-module-info.ts +412 -0
- package/src/compiler/transformers/for-await.ts +687 -0
- package/src/compiler/transformers/import-elision.ts +152 -0
- package/src/compiler/transformers/jsx-entities.ts +256 -0
- package/src/compiler/transformers/jsx.ts +824 -0
- package/src/compiler/transformers/legacy-decorators.ts +726 -0
- package/src/compiler/transformers/logical-assignment.ts +75 -0
- package/src/compiler/transformers/module-utilities.ts +42 -0
- package/src/compiler/transformers/module.ts +474 -0
- package/src/compiler/transformers/named-evaluation.ts +389 -0
- package/src/compiler/transformers/nullish-coalescing.ts +35 -0
- package/src/compiler/transformers/object-rest-spread.ts +577 -0
- package/src/compiler/transformers/optional-catch.ts +29 -0
- package/src/compiler/transformers/optional-chain.ts +246 -0
- package/src/compiler/transformers/reference-resolver.ts +1213 -0
- package/src/compiler/transformers/runtime-syntax.ts +942 -0
- package/src/compiler/transformers/subtree-facts.ts +253 -0
- package/src/compiler/transformers/syntax-facts.ts +358 -0
- package/src/compiler/transformers/tagged-template.ts +167 -0
- package/src/compiler/transformers/transformer.ts +56 -0
- package/src/compiler/transformers/type-eraser.ts +520 -0
- package/src/compiler/transformers/type-serialization.ts +374 -0
- package/src/compiler/transformers/using.ts +613 -0
- package/src/compiler/transformers/utilities.ts +419 -0
- package/src/compiler/transformers/visitor-base.ts +1601 -0
- package/src/compiler/transformers/visitor-hooks.ts +252 -0
- package/src/compiler/tsc-build.ts +1422 -0
- package/src/compiler/tsc-cli.ts +669 -0
- package/src/compiler/tsc-compile.ts +446 -0
- package/src/compiler/tsc-watch.ts +922 -0
- package/src/compiler/tsconfig.ts +1574 -0
- package/src/compiler/type-printer.ts +110 -0
- package/src/compiler/types.ts +115 -0
- package/src/compiler/unicode-identifiers.ts +212 -0
- package/src/compiler/unicode-properties.ts +537 -0
- package/src/compiler/vfs-match.ts +597 -0
- package/src/compiler/xxh3.ts +650 -0
- package/src/library/ast.generated.ts +141 -167
- package/src/library/ast.ts +4 -1
- package/src/library/checker.ts +384 -0
- package/src/library/diagnostics.ts +72 -0
- package/src/library/disk.ts +73 -0
- package/src/library/errors.ts +26 -0
- package/src/library/host.ts +63 -0
- package/src/library/index.ts +21 -0
- package/src/library/nodes.ts +232 -0
- package/src/library/options.ts +449 -0
- package/src/library/parse.ts +63 -0
- package/src/library/program.ts +293 -0
- package/src/library/types.ts +14 -1
|
@@ -0,0 +1,3433 @@
|
|
|
1
|
+
// Building type nodes from types, like tsgo's node builder: `typeToTypeNode` and
|
|
2
|
+
// `signatureToSignatureDeclaration` for the API, and the serializers declaration emit uses.
|
|
3
|
+
//
|
|
4
|
+
// A `NodeBuilder` is one serialization: its fields are tsgo's node builder context. Naming
|
|
5
|
+
// symbols is in node-builder-names.ts and reusing existing type nodes in node-builder-reuse.ts.
|
|
6
|
+
import { sideOf } from './side-state.js';
|
|
7
|
+
import { utf8Length } from './character-codes.js';
|
|
8
|
+
import {
|
|
9
|
+
ArrayTypeNode,
|
|
10
|
+
ArrowFunction,
|
|
11
|
+
BinaryExpression,
|
|
12
|
+
ElementAccessExpression,
|
|
13
|
+
ImportTypeNode,
|
|
14
|
+
NodeVisitor,
|
|
15
|
+
getExpression,
|
|
16
|
+
getParameters,
|
|
17
|
+
getPostfixToken,
|
|
18
|
+
getQuestionToken,
|
|
19
|
+
getSymbol,
|
|
20
|
+
BigIntLiteral,
|
|
21
|
+
BindingElement,
|
|
22
|
+
BindingPattern,
|
|
23
|
+
Block,
|
|
24
|
+
CallSignatureDeclaration,
|
|
25
|
+
ConditionalTypeNode,
|
|
26
|
+
ConstructSignatureDeclaration,
|
|
27
|
+
ConstructorDeclaration,
|
|
28
|
+
ConstructorTypeNode,
|
|
29
|
+
FunctionDeclaration,
|
|
30
|
+
FunctionExpression,
|
|
31
|
+
FunctionTypeNode,
|
|
32
|
+
GetAccessorDeclaration,
|
|
33
|
+
Identifier,
|
|
34
|
+
IndexSignatureDeclaration,
|
|
35
|
+
IndexedAccessTypeNode,
|
|
36
|
+
InferTypeNode,
|
|
37
|
+
IntersectionTypeNode,
|
|
38
|
+
KeywordTypeNode,
|
|
39
|
+
LiteralTypeNode,
|
|
40
|
+
MappedTypeNode,
|
|
41
|
+
MethodDeclaration,
|
|
42
|
+
MethodSignatureDeclaration,
|
|
43
|
+
ModifierFlags,
|
|
44
|
+
type ModifierList,
|
|
45
|
+
NamedTupleMember,
|
|
46
|
+
type Node,
|
|
47
|
+
NodeFlags,
|
|
48
|
+
NodeList,
|
|
49
|
+
NotEmittedTypeElement,
|
|
50
|
+
OptionalTypeNode,
|
|
51
|
+
ParameterDeclaration,
|
|
52
|
+
PrefixUnaryExpression,
|
|
53
|
+
PropertySignatureDeclaration,
|
|
54
|
+
QualifiedName,
|
|
55
|
+
RestTypeNode,
|
|
56
|
+
SetAccessorDeclaration,
|
|
57
|
+
type SourceFile,
|
|
58
|
+
StringLiteral,
|
|
59
|
+
TemplateHead,
|
|
60
|
+
TemplateLiteralTypeNode,
|
|
61
|
+
TemplateLiteralTypeSpan,
|
|
62
|
+
TemplateMiddle,
|
|
63
|
+
TemplateTail,
|
|
64
|
+
ThisTypeNode,
|
|
65
|
+
Token,
|
|
66
|
+
TupleTypeNode,
|
|
67
|
+
TypeLiteralNode,
|
|
68
|
+
TypeOperatorNode,
|
|
69
|
+
TypeParameterDeclaration,
|
|
70
|
+
TypePredicateNode,
|
|
71
|
+
TypeQueryNode,
|
|
72
|
+
TypeReferenceNode,
|
|
73
|
+
UnionTypeNode,
|
|
74
|
+
getModifiers,
|
|
75
|
+
getName,
|
|
76
|
+
getNodeId,
|
|
77
|
+
getText,
|
|
78
|
+
getType,
|
|
79
|
+
} from './ast.js';
|
|
80
|
+
import { isModifierKind, modifierToFlag } from './ast-utilities.js';
|
|
81
|
+
import {
|
|
82
|
+
declarationNameToString,
|
|
83
|
+
getCombinedModifierFlags,
|
|
84
|
+
getDeclarationOfKind,
|
|
85
|
+
getImmediatelyInvokedFunctionExpression,
|
|
86
|
+
getNameOfDeclaration,
|
|
87
|
+
getSourceFileOfNode,
|
|
88
|
+
getThisContainer,
|
|
89
|
+
hasSyntacticModifier,
|
|
90
|
+
isClassLike,
|
|
91
|
+
isEntityNameExpression,
|
|
92
|
+
isStatic,
|
|
93
|
+
symbolName,
|
|
94
|
+
} from './binder-utilities.js';
|
|
95
|
+
import { getEffectiveCallArguments } from './checker-calls.js';
|
|
96
|
+
import { getIntendedTypeFromJSDocTypeReference } from './checker-jsdoc.js';
|
|
97
|
+
import { type Checker, maxSerializationLevel } from './checker.js';
|
|
98
|
+
import {
|
|
99
|
+
getConstraintDeclaration,
|
|
100
|
+
getConstraintOfTypeParameter,
|
|
101
|
+
getDeclaredTypeOfClassOrInterface,
|
|
102
|
+
getDeclaredTypeOfSymbol,
|
|
103
|
+
getDefaultFromTypeParameter,
|
|
104
|
+
getLocalTypeParametersOfClassOrInterfaceOrTypeAlias,
|
|
105
|
+
getMinTypeArgumentCount,
|
|
106
|
+
} from './checker-declared-types.js';
|
|
107
|
+
import { getTypeWithFacts, TypeFacts } from './checker-flow.js';
|
|
108
|
+
import { getInferredTypeParameterConstraint } from './checker-inference.js';
|
|
109
|
+
import { getGlobalIterableIteratorType, getGlobalIterableType, isReferenceToType } from './checker-iteration.js';
|
|
110
|
+
import {
|
|
111
|
+
getDeclarationModifierFlagsFromSymbol,
|
|
112
|
+
getPropertiesOfObjectType,
|
|
113
|
+
getReducedType,
|
|
114
|
+
getSignaturesOfType,
|
|
115
|
+
getTargetSymbol,
|
|
116
|
+
membersHolder,
|
|
117
|
+
resolveStructuredTypeMembers,
|
|
118
|
+
} from './checker-members.js';
|
|
119
|
+
import {
|
|
120
|
+
getOrCreateTypeFromSignature,
|
|
121
|
+
getReturnTypeOfSignature,
|
|
122
|
+
getSignatureFromDeclaration,
|
|
123
|
+
getTypeParametersFromDeclaration,
|
|
124
|
+
getTypePredicateOfSignature,
|
|
125
|
+
instantiateTypePredicate,
|
|
126
|
+
} from './checker-signatures.js';
|
|
127
|
+
import {
|
|
128
|
+
getBaseTypeVariableOfClass,
|
|
129
|
+
getNonMissingTypeOfSymbol,
|
|
130
|
+
getOptionalType,
|
|
131
|
+
getTypeOfSymbol,
|
|
132
|
+
getWriteTypeOfSymbol,
|
|
133
|
+
isReadonlySymbol,
|
|
134
|
+
removeMissingType,
|
|
135
|
+
} from './checker-symbol-types.js';
|
|
136
|
+
import {
|
|
137
|
+
getFirstIdentifier,
|
|
138
|
+
getGlobalTypeAliasSymbol,
|
|
139
|
+
getMergedSymbol,
|
|
140
|
+
getParentOfSymbol,
|
|
141
|
+
getSymbolOfDeclaration,
|
|
142
|
+
resolveName,
|
|
143
|
+
} from './checker-symbols.js';
|
|
144
|
+
import {
|
|
145
|
+
createArrayType,
|
|
146
|
+
filterType,
|
|
147
|
+
getIntersectionType,
|
|
148
|
+
getTypeArguments,
|
|
149
|
+
getTypeReferenceArity,
|
|
150
|
+
getWidenedLiteralType,
|
|
151
|
+
isErrorType,
|
|
152
|
+
isTupleType,
|
|
153
|
+
inDeclarationOrder,
|
|
154
|
+
newAnonymousType,
|
|
155
|
+
} from './checker-type-factory.js';
|
|
156
|
+
import { getTypeFromTypeNode } from './checker-type-nodes.js';
|
|
157
|
+
import {
|
|
158
|
+
MappedTypeModifiers,
|
|
159
|
+
getConstraintTypeFromMappedType,
|
|
160
|
+
getFalseTypeFromConditionalType,
|
|
161
|
+
getHomomorphicTypeVariable,
|
|
162
|
+
getMappedTypeModifiers,
|
|
163
|
+
getModifiersTypeFromMappedType,
|
|
164
|
+
getNameTypeFromMappedType,
|
|
165
|
+
getTemplateTypeFromMappedType,
|
|
166
|
+
getTrueTypeFromConditionalType,
|
|
167
|
+
getTypeParameterFromMappedType,
|
|
168
|
+
isGenericMappedType,
|
|
169
|
+
isMappedTypeWithKeyofConstraintDeclaration,
|
|
170
|
+
isNoInferType,
|
|
171
|
+
} from './checker-type-operators.js';
|
|
172
|
+
import {
|
|
173
|
+
type ConditionalType,
|
|
174
|
+
ElementFlags,
|
|
175
|
+
type IndexInfo,
|
|
176
|
+
type IndexType,
|
|
177
|
+
type IndexedAccessType,
|
|
178
|
+
type InstantiationExpressionType,
|
|
179
|
+
type InterfaceType,
|
|
180
|
+
type LiteralType,
|
|
181
|
+
type MappedType,
|
|
182
|
+
ObjectFlags,
|
|
183
|
+
Signature,
|
|
184
|
+
SignatureFlags,
|
|
185
|
+
SignatureKind,
|
|
186
|
+
type StringMappingType,
|
|
187
|
+
type StructuredType,
|
|
188
|
+
type SubstitutionType,
|
|
189
|
+
type TemplateLiteralType,
|
|
190
|
+
type TupleType,
|
|
191
|
+
type Type,
|
|
192
|
+
TypeFlags,
|
|
193
|
+
type TypeMapper,
|
|
194
|
+
type TypeParameter,
|
|
195
|
+
type TypePredicate,
|
|
196
|
+
TypePredicateKind,
|
|
197
|
+
type TypeReference,
|
|
198
|
+
type UnionType,
|
|
199
|
+
type UnionOrIntersectionType,
|
|
200
|
+
newTypeMapper,
|
|
201
|
+
prependTypeMapping,
|
|
202
|
+
} from './checker-types.js';
|
|
203
|
+
import {
|
|
204
|
+
hasLateBindableIndexSignature,
|
|
205
|
+
hasLateBindableName,
|
|
206
|
+
isLateBindableName,
|
|
207
|
+
isLateBoundName,
|
|
208
|
+
} from './checker-utilities.js';
|
|
209
|
+
import { instantiateSignature, instantiateType } from './instantiation.js';
|
|
210
|
+
import { EmitContext } from './printer/emit-context.js';
|
|
211
|
+
import { EmitFlags } from './printer/emit-flags.js';
|
|
212
|
+
import { Printer, PrinterOptions } from './printer/printer.js';
|
|
213
|
+
import { TextWriter } from './printer/text-writer.js';
|
|
214
|
+
import type { NodeFactory } from './printer/factory.js';
|
|
215
|
+
import { isTypeIdenticalTo } from './relations.js';
|
|
216
|
+
import { isIdentifierText } from './scanner.js';
|
|
217
|
+
import { SyntaxKind } from './syntax-kind.js';
|
|
218
|
+
import {
|
|
219
|
+
NodeBuilderFlags,
|
|
220
|
+
NodeBuilderInternalFlags,
|
|
221
|
+
SymbolAccessibility,
|
|
222
|
+
SymbolAccessibilityResult,
|
|
223
|
+
SymbolTracker,
|
|
224
|
+
accessible,
|
|
225
|
+
} from './transformers/declarations-resolver.js';
|
|
226
|
+
import { getMeaningOfEntityNameReference } from './transformers/declarations-syntactic.js';
|
|
227
|
+
import { TokenFlags } from './types.js';
|
|
228
|
+
import { formatUnionTypes, symbolToString } from './type-printer.js';
|
|
229
|
+
import {
|
|
230
|
+
hasVisibleDeclarations,
|
|
231
|
+
isSymbolAccessible,
|
|
232
|
+
isTypeSymbolAccessible,
|
|
233
|
+
isValueSymbolAccessible,
|
|
234
|
+
} from './symbol-accessibility.js';
|
|
235
|
+
import {
|
|
236
|
+
getPropertyNameNodeForSymbol,
|
|
237
|
+
symbolToEntityNameNode,
|
|
238
|
+
symbolToExpression,
|
|
239
|
+
symbolToName,
|
|
240
|
+
symbolToTypeNode,
|
|
241
|
+
appendReferenceToType,
|
|
242
|
+
} from './node-builder-names.js';
|
|
243
|
+
import { tryReuseExistingNode } from './node-builder-reuse.js';
|
|
244
|
+
import {
|
|
245
|
+
containsNonMissingUndefinedType,
|
|
246
|
+
hasInferredTypeKind,
|
|
247
|
+
hasQuestionToken,
|
|
248
|
+
isAccessorKind,
|
|
249
|
+
pseudoReturnTypeMatchesPredicate,
|
|
250
|
+
pseudoTypeEquivalentToType,
|
|
251
|
+
pseudoTypeToNodeWithCheckerFallback,
|
|
252
|
+
pseudoTypeToType,
|
|
253
|
+
newPseudoChecker,
|
|
254
|
+
requiresAddingImplicitUndefinedForDeclaration,
|
|
255
|
+
} from './node-builder-pseudo.js';
|
|
256
|
+
import {
|
|
257
|
+
InferredType,
|
|
258
|
+
type PseudoChecker,
|
|
259
|
+
type PseudoType,
|
|
260
|
+
PseudoTypeKind,
|
|
261
|
+
UnionType as PseudoUnionType,
|
|
262
|
+
couldAlreadyReferToUndefined,
|
|
263
|
+
undefinedType as pseudoUndefinedType,
|
|
264
|
+
} from './transformers/declarations-pseudo.js';
|
|
265
|
+
import {
|
|
266
|
+
CheckFlags,
|
|
267
|
+
declarationCount,
|
|
268
|
+
getDeclarations,
|
|
269
|
+
getSymbolId,
|
|
270
|
+
type Symbol,
|
|
271
|
+
SymbolFlags,
|
|
272
|
+
type SymbolTable,
|
|
273
|
+
} from './symbol.js';
|
|
274
|
+
|
|
275
|
+
const defaultMaximumTruncationLength = 160;
|
|
276
|
+
const noTruncationMaximumTruncationLength = 1_000_000;
|
|
277
|
+
const maxReverseMappedNestingInspectionDepth = 3;
|
|
278
|
+
|
|
279
|
+
/** A symbol the builder named, kept with a cached result so it can be tracked again. */
|
|
280
|
+
export class TrackedSymbol {
|
|
281
|
+
readonly symbol: Symbol;
|
|
282
|
+
readonly enclosingDeclaration: Node | undefined;
|
|
283
|
+
readonly meaning: SymbolFlags;
|
|
284
|
+
|
|
285
|
+
constructor(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags) {
|
|
286
|
+
this.symbol = symbol;
|
|
287
|
+
this.enclosingDeclaration = enclosingDeclaration;
|
|
288
|
+
this.meaning = meaning;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
class SerializedTypeEntry {
|
|
293
|
+
readonly node: Node;
|
|
294
|
+
readonly truncating: boolean;
|
|
295
|
+
readonly addedLength: number;
|
|
296
|
+
readonly trackedSymbols: TrackedSymbol[];
|
|
297
|
+
|
|
298
|
+
constructor(node: Node, truncating: boolean, addedLength: number, trackedSymbols: TrackedSymbol[]) {
|
|
299
|
+
this.node = node;
|
|
300
|
+
this.truncating = truncating;
|
|
301
|
+
this.addedLength = addedLength;
|
|
302
|
+
this.trackedSymbols = trackedSymbols;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* What a builder's tracker records for it. The builder and its tracker share it, so the tracker doesn't refer to
|
|
308
|
+
* the builder: a builder and a tracker that pointed at each other made every builder a reference cycle.
|
|
309
|
+
*/
|
|
310
|
+
export class BuilderReports {
|
|
311
|
+
reportedDiagnostic = false;
|
|
312
|
+
trackedSymbols: TrackedSymbol[] = [];
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* The tracker a builder reports to: records the symbols it names and that a diagnostic was
|
|
317
|
+
* reported (`BuilderReports`), and forwards to the caller's tracker, if any.
|
|
318
|
+
*/
|
|
319
|
+
export class BuilderTracker extends SymbolTracker {
|
|
320
|
+
readonly reports: BuilderReports;
|
|
321
|
+
readonly inner: SymbolTracker | undefined;
|
|
322
|
+
|
|
323
|
+
constructor(reports: BuilderReports, inner: SymbolTracker | undefined) {
|
|
324
|
+
super();
|
|
325
|
+
this.reports = reports;
|
|
326
|
+
// Don't stack builder trackers.
|
|
327
|
+
let unwrapped = inner;
|
|
328
|
+
while (unwrapped instanceof BuilderTracker) unwrapped = unwrapped.inner;
|
|
329
|
+
this.inner = unwrapped;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
trackSymbol(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags): boolean {
|
|
333
|
+
if (this.inner !== undefined && this.inner.trackSymbol(symbol, enclosingDeclaration, meaning)) {
|
|
334
|
+
this.reports.reportedDiagnostic = true;
|
|
335
|
+
return true;
|
|
336
|
+
}
|
|
337
|
+
// Type parameters don't need late painted statements.
|
|
338
|
+
if ((symbol.flags & SymbolFlags.TypeParameter) === 0)
|
|
339
|
+
this.reports.trackedSymbols.push(new TrackedSymbol(symbol, enclosingDeclaration, meaning));
|
|
340
|
+
return false;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
reportInferenceFallback(node: Node): boolean {
|
|
344
|
+
return this.inner !== undefined && this.inner.reportInferenceFallback(node);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
reportCyclicStructureError(): boolean {
|
|
348
|
+
this.reports.reportedDiagnostic = true;
|
|
349
|
+
return this.inner !== undefined && this.inner.reportCyclicStructureError();
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
reportInaccessibleThisError(): boolean {
|
|
353
|
+
this.reports.reportedDiagnostic = true;
|
|
354
|
+
return this.inner !== undefined && this.inner.reportInaccessibleThisError();
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
reportInaccessibleUniqueSymbolError(): boolean {
|
|
358
|
+
this.reports.reportedDiagnostic = true;
|
|
359
|
+
return this.inner !== undefined && this.inner.reportInaccessibleUniqueSymbolError();
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
reportLikelyUnsafeImportRequiredError(specifier: string, symbolName: string): boolean {
|
|
363
|
+
this.reports.reportedDiagnostic = true;
|
|
364
|
+
return this.inner !== undefined && this.inner.reportLikelyUnsafeImportRequiredError(specifier, symbolName);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
reportNonSerializableProperty(propertyName: string): boolean {
|
|
368
|
+
this.reports.reportedDiagnostic = true;
|
|
369
|
+
return this.inner !== undefined && this.inner.reportNonSerializableProperty(propertyName);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
reportPrivateInBaseOfClassExpression(propertyName: string): boolean {
|
|
373
|
+
this.reports.reportedDiagnostic = true;
|
|
374
|
+
return this.inner !== undefined && this.inner.reportPrivateInBaseOfClassExpression(propertyName);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
reportTruncationError(): boolean {
|
|
378
|
+
this.reports.reportedDiagnostic = true;
|
|
379
|
+
return this.inner !== undefined && this.inner.reportTruncationError();
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
reportNonlocalAugmentation(containingFile: SourceFile, parentSymbol: Symbol, augmentingSymbol: Symbol): boolean {
|
|
383
|
+
this.reports.reportedDiagnostic = true;
|
|
384
|
+
return (
|
|
385
|
+
this.inner !== undefined && this.inner.reportNonlocalAugmentation(containingFile, parentSymbol, augmentingSymbol)
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
pushErrorFallbackNode(node: Node): boolean {
|
|
390
|
+
return this.inner !== undefined && this.inner.pushErrorFallbackNode(node);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
popErrorFallbackNode(): boolean {
|
|
394
|
+
return this.inner !== undefined && this.inner.popErrorFallbackNode();
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/** What `signatureToSignatureDeclaration` may add to the declaration. */
|
|
399
|
+
class SignatureDeclarationOptions {
|
|
400
|
+
readonly modifiers: Node[];
|
|
401
|
+
readonly name: Node | undefined;
|
|
402
|
+
readonly questionToken: Token | undefined;
|
|
403
|
+
|
|
404
|
+
constructor(modifiers: Node[], name: Node | undefined, questionToken: Token | undefined) {
|
|
405
|
+
this.modifiers = modifiers;
|
|
406
|
+
this.name = name;
|
|
407
|
+
this.questionToken = questionToken;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
export const enum PropertyNameKind {
|
|
412
|
+
Identifier,
|
|
413
|
+
NumericLiteral,
|
|
414
|
+
StringLiteral,
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
export function classifyPropertyName(name: string, stringNamed: boolean, isMethod: boolean): PropertyNameKind {
|
|
418
|
+
if (isMethod && name === 'new') return PropertyNameKind.StringLiteral;
|
|
419
|
+
if (isIdentifierText(name)) return PropertyNameKind.Identifier;
|
|
420
|
+
return !stringNamed && isNumericLiteralName(name) && Number(name) >= 0
|
|
421
|
+
? PropertyNameKind.NumericLiteral
|
|
422
|
+
: PropertyNameKind.StringLiteral;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
export function isNumericLiteralName(name: string): boolean {
|
|
426
|
+
return String(Number(name)) === name;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/** One serialization of types to nodes. */
|
|
430
|
+
export class NodeBuilder {
|
|
431
|
+
readonly c: Checker;
|
|
432
|
+
readonly context: EmitContext;
|
|
433
|
+
readonly factory: NodeFactory;
|
|
434
|
+
tracker: SymbolTracker;
|
|
435
|
+
flags: NodeBuilderFlags;
|
|
436
|
+
internalFlags: NodeBuilderInternalFlags;
|
|
437
|
+
approximateLength = 0;
|
|
438
|
+
encounteredError = false;
|
|
439
|
+
truncating = false;
|
|
440
|
+
enclosingDeclaration: Node | undefined;
|
|
441
|
+
readonly enclosingFile: SourceFile | undefined;
|
|
442
|
+
inferTypeParameters: Type[] = [];
|
|
443
|
+
private visitedTypesStore: Set<number> | undefined = undefined;
|
|
444
|
+
private symbolDepthStore: Map<string, number> | undefined = undefined;
|
|
445
|
+
/** What its tracker records (`reportedDiagnostic`, `trackedSymbols`). */
|
|
446
|
+
readonly reports = new BuilderReports();
|
|
447
|
+
mapper: TypeMapper | undefined = undefined;
|
|
448
|
+
private reverseMappedStackStore: Symbol[] | undefined = undefined;
|
|
449
|
+
private enclosingSymbolTypesStore: Map<number, Type> | undefined = undefined;
|
|
450
|
+
suppressReportInferenceFallback = false;
|
|
451
|
+
private remappedSymbolReferencesStore: Map<number, Symbol> | undefined = undefined;
|
|
452
|
+
// Per signature scope; undefined while empty.
|
|
453
|
+
typeParameterNames: Map<number, Identifier> | undefined = undefined;
|
|
454
|
+
typeParameterNamesByText: Set<string> | undefined = undefined;
|
|
455
|
+
typeParameterNamesByTextNextNameCount: Map<string, number> | undefined = undefined;
|
|
456
|
+
typeParameterSymbolList: Set<number> | undefined = undefined;
|
|
457
|
+
private serializedTypesStore: Map<number, Map<string, SerializedTypeEntry>> | undefined = undefined;
|
|
458
|
+
private fakeScopesStore: Map<Node, string> | undefined = undefined;
|
|
459
|
+
/**
|
|
460
|
+
* Declaration emit's pseudochecker: with it, types of declarations are written from what the
|
|
461
|
+
* source wrote where that denotes the checker's type.
|
|
462
|
+
*/
|
|
463
|
+
pseudo: PseudoChecker | undefined = undefined;
|
|
464
|
+
/** Set for declaration emit, which writes unions in an order that doesn't depend on the checker's history. */
|
|
465
|
+
declarationOrder = false;
|
|
466
|
+
|
|
467
|
+
constructor(
|
|
468
|
+
c: Checker,
|
|
469
|
+
enclosingDeclaration: Node | undefined,
|
|
470
|
+
flags: NodeBuilderFlags,
|
|
471
|
+
internalFlags: NodeBuilderInternalFlags,
|
|
472
|
+
tracker: SymbolTracker | undefined,
|
|
473
|
+
context: EmitContext | undefined = undefined,
|
|
474
|
+
) {
|
|
475
|
+
this.c = c;
|
|
476
|
+
this.context = context ?? new EmitContext();
|
|
477
|
+
this.factory = this.context.factory;
|
|
478
|
+
this.flags = flags;
|
|
479
|
+
this.internalFlags = internalFlags;
|
|
480
|
+
this.enclosingDeclaration = enclosingDeclaration;
|
|
481
|
+
this.enclosingFile = enclosingDeclaration === undefined ? undefined : getSourceFileOfNode(enclosingDeclaration);
|
|
482
|
+
this.tracker = new BuilderTracker(this.reports, tracker);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
get reportedDiagnostic(): boolean {
|
|
486
|
+
return this.reports.reportedDiagnostic;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
set reportedDiagnostic(value: boolean) {
|
|
490
|
+
this.reports.reportedDiagnostic = value;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
get trackedSymbols(): TrackedSymbol[] {
|
|
494
|
+
return this.reports.trackedSymbols;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
set trackedSymbols(value: TrackedSymbol[]) {
|
|
498
|
+
this.reports.trackedSymbols = value;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// Created when first used: most types a builder writes need none of these.
|
|
502
|
+
|
|
503
|
+
get visitedTypes(): Set<number> {
|
|
504
|
+
return (this.visitedTypesStore ??= new Set<number>());
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/** Nesting depth of each symbol, node or constructor being written. */
|
|
508
|
+
get symbolDepth(): Map<string, number> {
|
|
509
|
+
return (this.symbolDepthStore ??= new Map<string, number>());
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
get reverseMappedStack(): Symbol[] {
|
|
513
|
+
return (this.reverseMappedStackStore ??= []);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/** Types of symbols being written, which may differ from their declared types. */
|
|
517
|
+
get enclosingSymbolTypes(): Map<number, Type> {
|
|
518
|
+
return (this.enclosingSymbolTypesStore ??= new Map<number, Type>());
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
get remappedSymbolReferences(): Map<number, Symbol> {
|
|
522
|
+
return (this.remappedSymbolReferencesStore ??= new Map<number, Symbol>());
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
/** Serialized types by enclosing declaration id, then type, flags and internal flags. */
|
|
526
|
+
get serializedTypes(): Map<number, Map<string, SerializedTypeEntry>> {
|
|
527
|
+
return (this.serializedTypesStore ??= new Map<number, Map<string, SerializedTypeEntry>>());
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
/** The kind of fake scope a block stands for: `params` or `typeParams`. */
|
|
531
|
+
get fakeScopes(): Map<Node, string> {
|
|
532
|
+
return (this.fakeScopesStore ??= new Map<Node, string>());
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
/** `result`, or undefined if serialization failed. */
|
|
536
|
+
finish<T>(result: T | undefined): T | undefined {
|
|
537
|
+
if (this.truncating && (this.flags & NodeBuilderFlags.NoTruncation) !== 0) this.tracker.reportTruncationError();
|
|
538
|
+
return this.encounteredError ? undefined : result;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/** Reports a symbol the builder names; without a location it's only recorded. */
|
|
542
|
+
trackSymbol(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags): void {
|
|
543
|
+
if (enclosingDeclaration !== undefined) this.tracker.trackSymbol(symbol, enclosingDeclaration, meaning);
|
|
544
|
+
else if ((symbol.flags & SymbolFlags.TypeParameter) === 0)
|
|
545
|
+
this.trackedSymbols.push(new TrackedSymbol(symbol, enclosingDeclaration, meaning));
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
checkTruncationLength(): boolean {
|
|
549
|
+
if (this.truncating) return true;
|
|
550
|
+
const maxLength =
|
|
551
|
+
(this.flags & NodeBuilderFlags.NoTruncation) !== 0
|
|
552
|
+
? noTruncationMaximumTruncationLength
|
|
553
|
+
: defaultMaximumTruncationLength;
|
|
554
|
+
this.truncating = this.approximateLength > maxLength;
|
|
555
|
+
return this.truncating;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
// ---- Node creation
|
|
559
|
+
|
|
560
|
+
created<T extends Node>(node: T): T {
|
|
561
|
+
return this.factory.created(node);
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
list(nodes: Node[]): NodeList {
|
|
565
|
+
return this.factory.createNodeList(nodes);
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
modifierList(nodes: Node[]): ModifierList | undefined {
|
|
569
|
+
return nodes.length === 0 ? undefined : this.factory.createModifierList(nodes);
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
keyword(kind: SyntaxKind): Node {
|
|
573
|
+
return this.created(new KeywordTypeNode(kind));
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
token(kind: SyntaxKind): Token {
|
|
577
|
+
return this.factory.createToken(kind);
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
identifier(text: string): Identifier {
|
|
581
|
+
return this.factory.createIdentifier(text);
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
stringLiteral(text: string, isSingleQuote: boolean): StringLiteral {
|
|
585
|
+
const flags =
|
|
586
|
+
isSingleQuote || (this.flags & NodeBuilderFlags.UseSingleQuotesForStringLiteralType) !== 0
|
|
587
|
+
? TokenFlags.SingleQuote
|
|
588
|
+
: TokenFlags.None;
|
|
589
|
+
return this.factory.createStringLiteral(text, flags);
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
typeReference(name: Node, typeArguments: NodeList | undefined): Node {
|
|
593
|
+
return this.created(new TypeReferenceNode(name, typeArguments));
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
/** `...`, or `any /*elided*\/` without truncation. */
|
|
597
|
+
createElidedInformationPlaceholder(): Node {
|
|
598
|
+
this.approximateLength += 3;
|
|
599
|
+
if ((this.flags & NodeBuilderFlags.NoTruncation) === 0)
|
|
600
|
+
return this.typeReference(this.identifier('...'), undefined);
|
|
601
|
+
return this.context.addSyntheticLeadingComment(
|
|
602
|
+
this.keyword(SyntaxKind.AnyKeyword),
|
|
603
|
+
SyntaxKind.MultiLineCommentTrivia,
|
|
604
|
+
'elided',
|
|
605
|
+
false,
|
|
606
|
+
);
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
// ---- Scopes
|
|
610
|
+
|
|
611
|
+
/** Sets the type `symbol` is written with until the returned function restores it. */
|
|
612
|
+
addSymbolTypeToContext(symbol: Symbol, t: Type): () => void {
|
|
613
|
+
const id = getSymbolId(symbol);
|
|
614
|
+
const old = this.enclosingSymbolTypes.get(id);
|
|
615
|
+
this.enclosingSymbolTypes.set(id, t);
|
|
616
|
+
return () => {
|
|
617
|
+
if (old !== undefined) this.enclosingSymbolTypes.set(id, old);
|
|
618
|
+
else this.enclosingSymbolTypes.delete(id);
|
|
619
|
+
};
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
/** Enters the scope of a signature, returning its exit; `expandedParameters` holds its parameters. */
|
|
623
|
+
enterSignatureScope(signature: Signature): () => void {
|
|
624
|
+
const expandedParams = getExpandedParameters(this.c, signature, true)[0]!;
|
|
625
|
+
this.expandedParameters = expandedParams;
|
|
626
|
+
return this.enterNewScope(
|
|
627
|
+
signature.declaration,
|
|
628
|
+
expandedParams,
|
|
629
|
+
signature.typeParameters,
|
|
630
|
+
signature.parameters,
|
|
631
|
+
signature.mapper,
|
|
632
|
+
);
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
/** The parameters of the signature scope entered last. */
|
|
636
|
+
expandedParameters: Symbol[] = [];
|
|
637
|
+
|
|
638
|
+
/**
|
|
639
|
+
* Enters a scope introducing parameters and type parameters. Names generated within it don't
|
|
640
|
+
* consume names outside it. The enclosing declaration gets a fake scope making the parameters
|
|
641
|
+
* visible, so names they shadow are qualified; it's shared along a chain of scopes.
|
|
642
|
+
*/
|
|
643
|
+
enterNewScope(
|
|
644
|
+
declaration: Node | undefined,
|
|
645
|
+
expandedParams: Symbol[] | undefined,
|
|
646
|
+
typeParameters: Type[] | undefined,
|
|
647
|
+
originalParameters: Symbol[] | undefined,
|
|
648
|
+
mapper: TypeMapper | undefined,
|
|
649
|
+
): () => void {
|
|
650
|
+
const savedNames = this.typeParameterNames;
|
|
651
|
+
const savedNamesByText = this.typeParameterNamesByText;
|
|
652
|
+
const savedNextNameCount = this.typeParameterNamesByTextNextNameCount;
|
|
653
|
+
const savedSymbolList = this.typeParameterSymbolList;
|
|
654
|
+
// The scope starts from the enclosing one's names, copied where there are any.
|
|
655
|
+
this.typeParameterNames = savedNames === undefined ? undefined : new Map<number, Identifier>(savedNames);
|
|
656
|
+
this.typeParameterNamesByText = savedNamesByText === undefined ? undefined : new Set<string>(savedNamesByText);
|
|
657
|
+
this.typeParameterNamesByTextNextNameCount =
|
|
658
|
+
savedNextNameCount === undefined ? undefined : new Map<string, number>(savedNextNameCount);
|
|
659
|
+
this.typeParameterSymbolList = savedSymbolList === undefined ? undefined : new Set<number>(savedSymbolList);
|
|
660
|
+
const oldEnclosingDeclaration = this.enclosingDeclaration;
|
|
661
|
+
const oldMapper = this.mapper;
|
|
662
|
+
if (mapper !== undefined) this.mapper = mapper;
|
|
663
|
+
let cleanupParams: (() => void) | undefined = undefined;
|
|
664
|
+
let cleanupTypeParams: (() => void) | undefined = undefined;
|
|
665
|
+
if (this.enclosingDeclaration !== undefined && declaration !== undefined) {
|
|
666
|
+
if (expandedParams !== undefined && expandedParams.length > 0) {
|
|
667
|
+
const table = new Map<string, Symbol>();
|
|
668
|
+
for (let i = 0; i < expandedParams.length; i++) {
|
|
669
|
+
const param = expandedParams[i]!;
|
|
670
|
+
const originalParam =
|
|
671
|
+
originalParameters !== undefined && i < originalParameters.length ? originalParameters[i]! : undefined;
|
|
672
|
+
if (originalParameters !== undefined && originalParam !== param) {
|
|
673
|
+
// An expanded parameter can't be named; the original can.
|
|
674
|
+
if (originalParam !== undefined) table.set(originalParam.name, originalParam);
|
|
675
|
+
} else if (!this.addBindingPatternParameters(param, table)) table.set(param.name, param);
|
|
676
|
+
}
|
|
677
|
+
cleanupParams = this.pushFakeScope('params', table);
|
|
678
|
+
}
|
|
679
|
+
if (
|
|
680
|
+
(this.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams) !== 0 &&
|
|
681
|
+
typeParameters !== undefined &&
|
|
682
|
+
typeParameters.length > 0
|
|
683
|
+
) {
|
|
684
|
+
const table = new Map<string, Symbol>();
|
|
685
|
+
for (const typeParameter of typeParameters)
|
|
686
|
+
table.set(this.typeParameterToName(typeParameter).text, typeParameter.symbol!);
|
|
687
|
+
cleanupTypeParams = this.pushFakeScope('typeParams', table);
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
return () => {
|
|
691
|
+
if (cleanupParams !== undefined) cleanupParams();
|
|
692
|
+
if (cleanupTypeParams !== undefined) cleanupTypeParams();
|
|
693
|
+
this.typeParameterNames = savedNames;
|
|
694
|
+
this.typeParameterNamesByText = savedNamesByText;
|
|
695
|
+
this.typeParameterNamesByTextNextNameCount = savedNextNameCount;
|
|
696
|
+
this.typeParameterSymbolList = savedSymbolList;
|
|
697
|
+
this.enclosingDeclaration = oldEnclosingDeclaration;
|
|
698
|
+
this.mapper = oldMapper;
|
|
699
|
+
};
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
/** Adds the names bound by a destructured parameter; false if `param` isn't one. */
|
|
703
|
+
private addBindingPatternParameters(param: Symbol, table: SymbolTable): boolean {
|
|
704
|
+
for (const d of getDeclarations(param)) {
|
|
705
|
+
if (d.kind !== SyntaxKind.Parameter) continue;
|
|
706
|
+
const name = asBindingPattern(getName(d));
|
|
707
|
+
if (name !== undefined) {
|
|
708
|
+
this.addBindingPattern(name, table);
|
|
709
|
+
return true;
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
return false;
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
private addBindingPattern(pattern: BindingPattern, table: SymbolTable): void {
|
|
716
|
+
// Only the first element is visited, as tsgo does.
|
|
717
|
+
for (const e of pattern.elements.nodes) {
|
|
718
|
+
if (!(e instanceof BindingElement)) return;
|
|
719
|
+
const name = asBindingPattern(e.name);
|
|
720
|
+
if (name !== undefined) {
|
|
721
|
+
this.addBindingPattern(name, table);
|
|
722
|
+
return;
|
|
723
|
+
}
|
|
724
|
+
const symbol = getSymbolOfDeclaration(this.c, e);
|
|
725
|
+
if (symbol !== undefined) table.set(symbol.name, symbol);
|
|
726
|
+
return;
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
/** Adds `names` to the fake scope of `kind` at the enclosing declaration, creating it if needed. */
|
|
731
|
+
private pushFakeScope(kind: string, names: SymbolTable): (() => void) | undefined {
|
|
732
|
+
const enclosing = this.enclosingDeclaration!;
|
|
733
|
+
let existing: Node | undefined = undefined;
|
|
734
|
+
if (this.fakeScopes.get(enclosing) === kind) existing = enclosing;
|
|
735
|
+
else if (enclosing.parent !== undefined && this.fakeScopes.get(enclosing.parent) === kind)
|
|
736
|
+
existing = enclosing.parent;
|
|
737
|
+
if (existing === undefined) {
|
|
738
|
+
const fakeScope = this.created(new Block(this.list([]), false));
|
|
739
|
+
fakeScope.locals = names;
|
|
740
|
+
fakeScope.parent = enclosing;
|
|
741
|
+
this.fakeScopes.set(fakeScope, kind);
|
|
742
|
+
this.enclosingDeclaration = fakeScope;
|
|
743
|
+
return undefined;
|
|
744
|
+
}
|
|
745
|
+
const locals = (existing as Block).locals!;
|
|
746
|
+
const added: string[] = [];
|
|
747
|
+
const replaced = new Map<string, Symbol>();
|
|
748
|
+
for (const [name, symbol] of names) {
|
|
749
|
+
const old = locals.get(name);
|
|
750
|
+
if (old === undefined) added.push(name);
|
|
751
|
+
else replaced.set(name, old);
|
|
752
|
+
locals.set(name, symbol);
|
|
753
|
+
}
|
|
754
|
+
return () => {
|
|
755
|
+
for (const name of added) locals.delete(name);
|
|
756
|
+
for (const [name, symbol] of replaced) locals.set(name, symbol);
|
|
757
|
+
};
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
/** The enclosing declaration without fake scopes. */
|
|
761
|
+
getEnclosingDeclarationIgnoringFakeScope(): Node | undefined {
|
|
762
|
+
let enclosing = this.enclosingDeclaration;
|
|
763
|
+
while (enclosing !== undefined && this.fakeScopes.has(enclosing)) enclosing = enclosing.parent;
|
|
764
|
+
return enclosing;
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
// ---- Type lists
|
|
768
|
+
|
|
769
|
+
private elidedCount(count: number, noTruncation: boolean): Node {
|
|
770
|
+
if (noTruncation)
|
|
771
|
+
return this.context.addSyntheticLeadingComment(
|
|
772
|
+
this.keyword(SyntaxKind.AnyKeyword),
|
|
773
|
+
SyntaxKind.MultiLineCommentTrivia,
|
|
774
|
+
'... ' + count + ' more elided ...',
|
|
775
|
+
false,
|
|
776
|
+
);
|
|
777
|
+
return this.typeReference(this.identifier('... ' + count + ' more ...'), undefined);
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
/** Type nodes of `list`; a bare list (union or intersection members) truncates in the middle. */
|
|
781
|
+
mapToTypeNodes(list: readonly Type[], isBareList: boolean): NodeList | undefined {
|
|
782
|
+
if (list.length === 0) return undefined;
|
|
783
|
+
const noTruncation = (this.flags & NodeBuilderFlags.NoTruncation) !== 0;
|
|
784
|
+
if (this.checkTruncationLength()) {
|
|
785
|
+
if (!isBareList) {
|
|
786
|
+
const node = noTruncation
|
|
787
|
+
? this.context.addSyntheticLeadingComment(
|
|
788
|
+
this.keyword(SyntaxKind.AnyKeyword),
|
|
789
|
+
SyntaxKind.MultiLineCommentTrivia,
|
|
790
|
+
'elided',
|
|
791
|
+
false,
|
|
792
|
+
)
|
|
793
|
+
: this.typeReference(this.identifier('...'), undefined);
|
|
794
|
+
return this.list([node]);
|
|
795
|
+
}
|
|
796
|
+
if (list.length > 2) {
|
|
797
|
+
const nodes: Node[] = [];
|
|
798
|
+
const first = this.typeToTypeNode(list[0]!);
|
|
799
|
+
if (first !== undefined) nodes.push(first);
|
|
800
|
+
nodes.push(this.elidedCount(list.length - 2, noTruncation));
|
|
801
|
+
const last = this.typeToTypeNode(list[list.length - 1]!);
|
|
802
|
+
if (last !== undefined) nodes.push(last);
|
|
803
|
+
return this.list(nodes);
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
const mayHaveNameCollisions = (this.flags & NodeBuilderFlags.UseFullyQualifiedType) === 0;
|
|
807
|
+
// Single-identifier references: indexes into `seenTypes`/`seenIndexes` by name.
|
|
808
|
+
const seenNames = new Map<string, number[]>();
|
|
809
|
+
const seenTypes: Type[] = [];
|
|
810
|
+
const seenIndexes: number[] = [];
|
|
811
|
+
const result: Node[] = [];
|
|
812
|
+
for (let i = 0; i < list.length; i++) {
|
|
813
|
+
const t = list[i]!;
|
|
814
|
+
const displayIndex = i + 1;
|
|
815
|
+
if (this.checkTruncationLength() && displayIndex + 2 < list.length - 1) {
|
|
816
|
+
result.push(this.elidedCount(list.length - displayIndex, noTruncation));
|
|
817
|
+
const last = this.typeToTypeNode(list[list.length - 1]!);
|
|
818
|
+
if (last !== undefined) result.push(last);
|
|
819
|
+
break;
|
|
820
|
+
}
|
|
821
|
+
this.approximateLength += 2;
|
|
822
|
+
const typeNode = this.typeToTypeNode(t);
|
|
823
|
+
if (typeNode === undefined) continue;
|
|
824
|
+
result.push(typeNode);
|
|
825
|
+
if (mayHaveNameCollisions && typeNode instanceof TypeReferenceNode && typeNode.typeName instanceof Identifier) {
|
|
826
|
+
const name = typeNode.typeName.text;
|
|
827
|
+
let indexes = seenNames.get(name);
|
|
828
|
+
if (indexes === undefined) {
|
|
829
|
+
indexes = [];
|
|
830
|
+
seenNames.set(name, indexes);
|
|
831
|
+
}
|
|
832
|
+
indexes.push(seenTypes.length);
|
|
833
|
+
seenTypes.push(t);
|
|
834
|
+
seenIndexes.push(result.length - 1);
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
if (mayHaveNameCollisions) {
|
|
838
|
+
// References by one name to different types are written qualified, so `[Foo, Foo]`
|
|
839
|
+
// doesn't hide that they come from different namespaces.
|
|
840
|
+
const savedFlags = this.flags;
|
|
841
|
+
this.flags |= NodeBuilderFlags.UseFullyQualifiedType;
|
|
842
|
+
for (const indexes of seenNames.values()) {
|
|
843
|
+
let homogeneous = true;
|
|
844
|
+
for (let k = 1; k < indexes.length; k++)
|
|
845
|
+
if (!typesAreSameReference(seenTypes[indexes[0]!]!, seenTypes[indexes[k]!]!)) homogeneous = false;
|
|
846
|
+
if (homogeneous) continue;
|
|
847
|
+
for (const k of indexes) {
|
|
848
|
+
const node = this.typeToTypeNode(seenTypes[k]!);
|
|
849
|
+
if (node !== undefined) result[seenIndexes[k]!] = node;
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
this.flags = savedFlags;
|
|
853
|
+
}
|
|
854
|
+
return this.list(result);
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
// ---- Types
|
|
858
|
+
|
|
859
|
+
typeToTypeNode(type: Type | undefined): Node | undefined {
|
|
860
|
+
const c = this.c;
|
|
861
|
+
const inTypeAlias = this.flags & NodeBuilderFlags.InTypeAlias;
|
|
862
|
+
this.flags &= ~NodeBuilderFlags.InTypeAlias;
|
|
863
|
+
if (type === undefined) {
|
|
864
|
+
if ((this.flags & NodeBuilderFlags.AllowEmptyUnionOrIntersection) === 0) {
|
|
865
|
+
this.encounteredError = true;
|
|
866
|
+
return undefined;
|
|
867
|
+
}
|
|
868
|
+
this.approximateLength += 3;
|
|
869
|
+
return this.keyword(SyntaxKind.AnyKeyword);
|
|
870
|
+
}
|
|
871
|
+
let t = type;
|
|
872
|
+
if ((this.flags & NodeBuilderFlags.NoTypeReduction) === 0) t = getReducedType(c, t);
|
|
873
|
+
const flags = t.flags;
|
|
874
|
+
if ((flags & TypeFlags.Any) !== 0) {
|
|
875
|
+
if (t.alias !== undefined)
|
|
876
|
+
return this.typeReference(
|
|
877
|
+
symbolToEntityNameNode(this, t.alias.symbol),
|
|
878
|
+
this.mapToTypeNodes(t.alias.typeArguments, false),
|
|
879
|
+
);
|
|
880
|
+
if (t === c.unresolvedType)
|
|
881
|
+
return this.context.addSyntheticLeadingComment(
|
|
882
|
+
this.keyword(SyntaxKind.AnyKeyword),
|
|
883
|
+
SyntaxKind.MultiLineCommentTrivia,
|
|
884
|
+
'unresolved',
|
|
885
|
+
false,
|
|
886
|
+
);
|
|
887
|
+
this.approximateLength += 3;
|
|
888
|
+
return this.keyword(t === c.intrinsicMarkerType ? SyntaxKind.IntrinsicKeyword : SyntaxKind.AnyKeyword);
|
|
889
|
+
}
|
|
890
|
+
if ((flags & TypeFlags.Unknown) !== 0) return this.keyword(SyntaxKind.UnknownKeyword);
|
|
891
|
+
if ((flags & TypeFlags.String) !== 0) {
|
|
892
|
+
this.approximateLength += 6;
|
|
893
|
+
return this.keyword(SyntaxKind.StringKeyword);
|
|
894
|
+
}
|
|
895
|
+
if ((flags & TypeFlags.Number) !== 0) {
|
|
896
|
+
this.approximateLength += 6;
|
|
897
|
+
return this.keyword(SyntaxKind.NumberKeyword);
|
|
898
|
+
}
|
|
899
|
+
if ((flags & TypeFlags.BigInt) !== 0) {
|
|
900
|
+
this.approximateLength += 6;
|
|
901
|
+
return this.keyword(SyntaxKind.BigIntKeyword);
|
|
902
|
+
}
|
|
903
|
+
if ((flags & TypeFlags.Boolean) !== 0 && t.alias === undefined) {
|
|
904
|
+
this.approximateLength += 7;
|
|
905
|
+
return this.keyword(SyntaxKind.BooleanKeyword);
|
|
906
|
+
}
|
|
907
|
+
if ((flags & TypeFlags.EnumLike) !== 0) {
|
|
908
|
+
const symbol = t.symbol!;
|
|
909
|
+
if ((symbol.flags & SymbolFlags.EnumMember) !== 0) {
|
|
910
|
+
const parentSymbol = getParentOfSymbol(c, symbol)!;
|
|
911
|
+
const parentName = symbolToTypeNode(this, parentSymbol, SymbolFlags.Type, undefined)!;
|
|
912
|
+
if (getDeclaredTypeOfSymbol(c, parentSymbol) === t) return parentName;
|
|
913
|
+
const memberName = symbol.name;
|
|
914
|
+
if (isIdentifierText(memberName))
|
|
915
|
+
return appendReferenceToType(this, parentName, this.typeReference(this.identifier(memberName), undefined));
|
|
916
|
+
if (parentName instanceof ImportTypeNode) {
|
|
917
|
+
// Freshly made, so it can be changed in place.
|
|
918
|
+
parentName.isTypeOf = true;
|
|
919
|
+
return this.created(
|
|
920
|
+
new IndexedAccessTypeNode(
|
|
921
|
+
parentName,
|
|
922
|
+
this.created(new LiteralTypeNode(this.stringLiteral(memberName, false))),
|
|
923
|
+
),
|
|
924
|
+
);
|
|
925
|
+
}
|
|
926
|
+
if (parentName instanceof TypeReferenceNode)
|
|
927
|
+
return this.created(
|
|
928
|
+
new IndexedAccessTypeNode(
|
|
929
|
+
this.created(new TypeQueryNode(parentName.typeName, undefined)),
|
|
930
|
+
this.created(new LiteralTypeNode(this.stringLiteral(memberName, false))),
|
|
931
|
+
),
|
|
932
|
+
);
|
|
933
|
+
throw new Error('Unhandled type node kind returned from symbolToTypeNode');
|
|
934
|
+
}
|
|
935
|
+
return symbolToTypeNode(this, symbol, SymbolFlags.Type, undefined);
|
|
936
|
+
}
|
|
937
|
+
if ((flags & TypeFlags.StringLiteral) !== 0) {
|
|
938
|
+
const value = (t as LiteralType).stringValue;
|
|
939
|
+
this.approximateLength += value.length + 2;
|
|
940
|
+
const literal = this.stringLiteral(value, false);
|
|
941
|
+
this.context.addEmitFlags(literal, EmitFlags.NoAsciiEscaping);
|
|
942
|
+
return this.created(new LiteralTypeNode(literal));
|
|
943
|
+
}
|
|
944
|
+
if ((flags & TypeFlags.NumberLiteral) !== 0) {
|
|
945
|
+
const value = (t as LiteralType).numberValue;
|
|
946
|
+
const text = String(value);
|
|
947
|
+
this.approximateLength += text.length;
|
|
948
|
+
if (value < 0)
|
|
949
|
+
return this.created(
|
|
950
|
+
new LiteralTypeNode(
|
|
951
|
+
this.created(
|
|
952
|
+
new PrefixUnaryExpression(SyntaxKind.MinusToken, this.factory.createNumericLiteral(text.substring(1))),
|
|
953
|
+
),
|
|
954
|
+
),
|
|
955
|
+
);
|
|
956
|
+
return this.created(new LiteralTypeNode(this.factory.createNumericLiteral(text)));
|
|
957
|
+
}
|
|
958
|
+
if ((flags & TypeFlags.BigIntLiteral) !== 0) {
|
|
959
|
+
const text = (t as LiteralType).stringValue;
|
|
960
|
+
this.approximateLength += text.length + 1;
|
|
961
|
+
return this.created(new LiteralTypeNode(this.created(new BigIntLiteral(text + 'n', TokenFlags.None))));
|
|
962
|
+
}
|
|
963
|
+
if ((flags & TypeFlags.BooleanLiteral) !== 0) {
|
|
964
|
+
const isTrue = (t as LiteralType).stringValue === 'true';
|
|
965
|
+
this.approximateLength += isTrue ? 4 : 5;
|
|
966
|
+
return this.created(
|
|
967
|
+
new LiteralTypeNode(
|
|
968
|
+
this.factory.createKeywordExpression(isTrue ? SyntaxKind.TrueKeyword : SyntaxKind.FalseKeyword),
|
|
969
|
+
),
|
|
970
|
+
);
|
|
971
|
+
}
|
|
972
|
+
if ((flags & TypeFlags.UniqueESSymbol) !== 0) {
|
|
973
|
+
if ((this.flags & NodeBuilderFlags.AllowUniqueESSymbolType) === 0) {
|
|
974
|
+
if (isValueSymbolAccessible(c, t.symbol!, this.enclosingDeclaration)) {
|
|
975
|
+
this.approximateLength += 6;
|
|
976
|
+
return symbolToTypeNode(this, t.symbol!, SymbolFlags.Value, undefined);
|
|
977
|
+
}
|
|
978
|
+
this.tracker.reportInaccessibleUniqueSymbolError();
|
|
979
|
+
}
|
|
980
|
+
this.approximateLength += 13;
|
|
981
|
+
return this.created(new TypeOperatorNode(SyntaxKind.UniqueKeyword, this.keyword(SyntaxKind.SymbolKeyword)));
|
|
982
|
+
}
|
|
983
|
+
if ((flags & TypeFlags.Void) !== 0) {
|
|
984
|
+
this.approximateLength += 4;
|
|
985
|
+
return this.keyword(SyntaxKind.VoidKeyword);
|
|
986
|
+
}
|
|
987
|
+
if ((flags & TypeFlags.Undefined) !== 0) {
|
|
988
|
+
this.approximateLength += 9;
|
|
989
|
+
return this.keyword(SyntaxKind.UndefinedKeyword);
|
|
990
|
+
}
|
|
991
|
+
if ((flags & TypeFlags.Null) !== 0) {
|
|
992
|
+
this.approximateLength += 4;
|
|
993
|
+
return this.created(new LiteralTypeNode(this.factory.createKeywordExpression(SyntaxKind.NullKeyword)));
|
|
994
|
+
}
|
|
995
|
+
if ((flags & TypeFlags.Never) !== 0) {
|
|
996
|
+
this.approximateLength += 5;
|
|
997
|
+
return this.keyword(SyntaxKind.NeverKeyword);
|
|
998
|
+
}
|
|
999
|
+
if ((flags & TypeFlags.ESSymbol) !== 0) {
|
|
1000
|
+
this.approximateLength += 6;
|
|
1001
|
+
return this.keyword(SyntaxKind.SymbolKeyword);
|
|
1002
|
+
}
|
|
1003
|
+
if ((flags & TypeFlags.NonPrimitive) !== 0) {
|
|
1004
|
+
this.approximateLength += 6;
|
|
1005
|
+
return this.keyword(SyntaxKind.ObjectKeyword);
|
|
1006
|
+
}
|
|
1007
|
+
if ((flags & TypeFlags.TypeParameter) !== 0 && (t as TypeParameter).isThisType) {
|
|
1008
|
+
if ((this.flags & NodeBuilderFlags.InObjectTypeLiteral) !== 0) {
|
|
1009
|
+
if (!this.encounteredError && (this.flags & NodeBuilderFlags.AllowThisInObjectLiteral) === 0)
|
|
1010
|
+
this.encounteredError = true;
|
|
1011
|
+
this.tracker.reportInaccessibleThisError();
|
|
1012
|
+
}
|
|
1013
|
+
this.approximateLength += 4;
|
|
1014
|
+
return this.created(new ThisTypeNode());
|
|
1015
|
+
}
|
|
1016
|
+
if (
|
|
1017
|
+
inTypeAlias === 0 &&
|
|
1018
|
+
t.alias !== undefined &&
|
|
1019
|
+
((this.flags & NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope) !== 0 ||
|
|
1020
|
+
isTypeSymbolAccessible(c, t.alias.symbol, this.enclosingDeclaration))
|
|
1021
|
+
) {
|
|
1022
|
+
const symbol = t.alias.symbol;
|
|
1023
|
+
const typeArgumentNodes = this.mapToTypeNodes(t.alias.typeArguments, false);
|
|
1024
|
+
if (isReservedMemberName(symbol.name) && (symbol.flags & SymbolFlags.Class) === 0)
|
|
1025
|
+
return this.typeReference(this.identifier(''), typeArgumentNodes);
|
|
1026
|
+
if (
|
|
1027
|
+
typeArgumentNodes !== undefined &&
|
|
1028
|
+
typeArgumentNodes.nodes.length === 1 &&
|
|
1029
|
+
symbol === c.globalArrayType.symbol
|
|
1030
|
+
)
|
|
1031
|
+
return this.created(new ArrayTypeNode(typeArgumentNodes.nodes[0]!));
|
|
1032
|
+
return symbolToTypeNode(this, symbol, SymbolFlags.Type, typeArgumentNodes);
|
|
1033
|
+
}
|
|
1034
|
+
const objectFlags = t.objectFlags;
|
|
1035
|
+
if ((objectFlags & ObjectFlags.Reference) !== 0) {
|
|
1036
|
+
if ((t as TypeReference).node !== undefined) return this.visitAndTransformType(t, TransformKind.TypeReference);
|
|
1037
|
+
return this.typeReferenceToTypeNode(t as TypeReference);
|
|
1038
|
+
}
|
|
1039
|
+
if ((flags & TypeFlags.TypeParameter) !== 0 || (objectFlags & ObjectFlags.ClassOrInterface) !== 0) {
|
|
1040
|
+
if ((flags & TypeFlags.TypeParameter) !== 0 && this.inferTypeParameters.indexOf(t) >= 0) {
|
|
1041
|
+
this.approximateLength += t.symbol!.name.length + 6;
|
|
1042
|
+
let constraintNode: Node | undefined = undefined;
|
|
1043
|
+
const constraint = getConstraintOfTypeParameter(c, t);
|
|
1044
|
+
if (constraint !== undefined) {
|
|
1045
|
+
// Write `infer T extends C` unless the position implies the same constraint.
|
|
1046
|
+
const inferredConstraint = getInferredTypeParameterConstraint(c, t, true);
|
|
1047
|
+
if (inferredConstraint === undefined || !isTypeIdenticalTo(c, constraint, inferredConstraint)) {
|
|
1048
|
+
this.approximateLength += 9;
|
|
1049
|
+
constraintNode = this.typeToTypeNode(constraint);
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
return this.created(new InferTypeNode(this.typeParameterToDeclarationWithConstraint(t, constraintNode)));
|
|
1053
|
+
}
|
|
1054
|
+
if (
|
|
1055
|
+
(this.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams) !== 0 &&
|
|
1056
|
+
(flags & TypeFlags.TypeParameter) !== 0
|
|
1057
|
+
) {
|
|
1058
|
+
const name = this.typeParameterToName(t);
|
|
1059
|
+
this.approximateLength += name.text.length;
|
|
1060
|
+
return this.typeReference(this.identifier(name.text), undefined);
|
|
1061
|
+
}
|
|
1062
|
+
// A use of a type parameter, not its declaration: no constraint or default.
|
|
1063
|
+
if (t.symbol !== undefined) return symbolToTypeNode(this, t.symbol, SymbolFlags.Type, undefined);
|
|
1064
|
+
const varianceTypeParameter = c.varianceTypeParameter;
|
|
1065
|
+
let name = '?';
|
|
1066
|
+
if (
|
|
1067
|
+
(t === c.markerSuperTypeForCheck || t === c.markerSubTypeForCheck) &&
|
|
1068
|
+
varianceTypeParameter !== undefined &&
|
|
1069
|
+
varianceTypeParameter.symbol !== undefined
|
|
1070
|
+
)
|
|
1071
|
+
name = (t === c.markerSubTypeForCheck ? 'sub-' : 'super-') + varianceTypeParameter.symbol.name;
|
|
1072
|
+
return this.typeReference(this.identifier(name), undefined);
|
|
1073
|
+
}
|
|
1074
|
+
let u = t;
|
|
1075
|
+
if ((flags & TypeFlags.Union) !== 0 && (t as UnionType).origin !== undefined) u = (t as UnionType).origin!;
|
|
1076
|
+
if ((u.flags & (TypeFlags.Union | TypeFlags.Intersection)) !== 0) {
|
|
1077
|
+
let types: readonly Type[] =
|
|
1078
|
+
(u.flags & TypeFlags.Union) !== 0
|
|
1079
|
+
? formatUnionTypes(c, (u as UnionOrIntersectionType).types, false)
|
|
1080
|
+
: (u as UnionOrIntersectionType).types;
|
|
1081
|
+
// Declaration emit writes unions in an order that doesn't depend on the checker's history; type
|
|
1082
|
+
// text in messages keeps the union's order.
|
|
1083
|
+
if (this.declarationOrder && (u.flags & TypeFlags.Union) !== 0) types = inDeclarationOrder(c, types);
|
|
1084
|
+
if (types.length === 1) return this.typeToTypeNode(types[0]!);
|
|
1085
|
+
const typeNodes = this.mapToTypeNodes(types, true);
|
|
1086
|
+
if (typeNodes !== undefined && typeNodes.nodes.length > 0)
|
|
1087
|
+
return (u.flags & TypeFlags.Union) !== 0
|
|
1088
|
+
? this.created(new UnionTypeNode(typeNodes))
|
|
1089
|
+
: this.created(new IntersectionTypeNode(typeNodes));
|
|
1090
|
+
if (!this.encounteredError && (this.flags & NodeBuilderFlags.AllowEmptyUnionOrIntersection) === 0)
|
|
1091
|
+
this.encounteredError = true;
|
|
1092
|
+
return undefined;
|
|
1093
|
+
}
|
|
1094
|
+
if ((objectFlags & (ObjectFlags.Anonymous | ObjectFlags.Mapped)) !== 0)
|
|
1095
|
+
return this.createAnonymousTypeNode(u, false, false);
|
|
1096
|
+
if ((u.flags & TypeFlags.Index) !== 0) {
|
|
1097
|
+
this.approximateLength += 6;
|
|
1098
|
+
const indexTypeNode = this.typeToTypeNode((u as IndexType).target);
|
|
1099
|
+
return this.created(new TypeOperatorNode(SyntaxKind.KeyOfKeyword, indexTypeNode!));
|
|
1100
|
+
}
|
|
1101
|
+
if ((u.flags & TypeFlags.TemplateLiteral) !== 0) {
|
|
1102
|
+
const texts = (u as TemplateLiteralType).texts;
|
|
1103
|
+
const types = (u as TemplateLiteralType).types;
|
|
1104
|
+
const head = this.created(new TemplateHead(texts[0]!, '', TokenFlags.None));
|
|
1105
|
+
this.context.addEmitFlags(head, EmitFlags.NoAsciiEscaping);
|
|
1106
|
+
const spans: Node[] = [];
|
|
1107
|
+
for (let i = 0; i < types.length; i++) {
|
|
1108
|
+
let literal: Node;
|
|
1109
|
+
if (i < types.length - 1) literal = this.created(new TemplateMiddle(texts[i + 1]!, '', TokenFlags.None));
|
|
1110
|
+
else literal = this.created(new TemplateTail(texts[i + 1]!, '', TokenFlags.None));
|
|
1111
|
+
this.context.addEmitFlags(literal, EmitFlags.NoAsciiEscaping);
|
|
1112
|
+
spans.push(this.created(new TemplateLiteralTypeSpan(this.typeToTypeNode(types[i]!)!, literal)));
|
|
1113
|
+
}
|
|
1114
|
+
this.approximateLength += 2;
|
|
1115
|
+
return this.created(new TemplateLiteralTypeNode(head, this.list(spans)));
|
|
1116
|
+
}
|
|
1117
|
+
if ((u.flags & TypeFlags.StringMapping) !== 0) {
|
|
1118
|
+
const typeNode = this.typeToTypeNode((u as StringMappingType).target);
|
|
1119
|
+
return symbolToTypeNode(this, u.symbol!, SymbolFlags.Type, this.list(typeNode === undefined ? [] : [typeNode]));
|
|
1120
|
+
}
|
|
1121
|
+
if ((u.flags & TypeFlags.IndexedAccess) !== 0) {
|
|
1122
|
+
const objectTypeNode = this.typeToTypeNode((u as IndexedAccessType).objectType);
|
|
1123
|
+
const indexTypeNode = this.typeToTypeNode((u as IndexedAccessType).indexType);
|
|
1124
|
+
this.approximateLength += 2;
|
|
1125
|
+
return this.created(new IndexedAccessTypeNode(objectTypeNode!, indexTypeNode!));
|
|
1126
|
+
}
|
|
1127
|
+
if ((u.flags & TypeFlags.Conditional) !== 0) return this.visitAndTransformType(u, TransformKind.Conditional);
|
|
1128
|
+
if ((u.flags & TypeFlags.Substitution) !== 0) {
|
|
1129
|
+
const typeNode = this.typeToTypeNode((u as SubstitutionType).baseType);
|
|
1130
|
+
if (!isNoInferType(c, u)) return typeNode;
|
|
1131
|
+
const noInferSymbol = getGlobalTypeAliasSymbol(c, 'NoInfer', 1, false);
|
|
1132
|
+
if (noInferSymbol === undefined) return typeNode;
|
|
1133
|
+
return symbolToTypeNode(
|
|
1134
|
+
this,
|
|
1135
|
+
noInferSymbol,
|
|
1136
|
+
SymbolFlags.Type,
|
|
1137
|
+
this.list(typeNode === undefined ? [] : [typeNode]),
|
|
1138
|
+
);
|
|
1139
|
+
}
|
|
1140
|
+
throw new Error('Unhandled type in typeToTypeNode');
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
/** Writes `t` with `transform`, eliding its circular references; cached per enclosing declaration. */
|
|
1144
|
+
visitAndTransformType(t: Type, transform: TransformKind): Node | undefined {
|
|
1145
|
+
const typeId = t.id;
|
|
1146
|
+
const isConstructorObject =
|
|
1147
|
+
(t.objectFlags & ObjectFlags.Anonymous) !== 0 &&
|
|
1148
|
+
t.symbol !== undefined &&
|
|
1149
|
+
(t.symbol.flags & SymbolFlags.Class) !== 0;
|
|
1150
|
+
// Instantiations of one anonymous type share a symbol, so tracking symbols rather than
|
|
1151
|
+
// types catches circular references through them.
|
|
1152
|
+
let id: string | undefined = undefined;
|
|
1153
|
+
if ((t.objectFlags & ObjectFlags.Reference) !== 0 && (t as TypeReference).node !== undefined)
|
|
1154
|
+
id = 'n' + getNodeId((t as TypeReference).node!);
|
|
1155
|
+
else if ((t.flags & TypeFlags.Conditional) !== 0) id = 'n' + getNodeId((t as ConditionalType).root.node);
|
|
1156
|
+
else if (t.symbol !== undefined) id = (isConstructorObject ? 'c' : 's') + getSymbolId(t.symbol);
|
|
1157
|
+
const key = typeId + ':' + this.flags + ':' + this.internalFlags;
|
|
1158
|
+
if (this.enclosingDeclaration !== undefined) {
|
|
1159
|
+
const cached = this.serializedTypes.get(getNodeId(this.enclosingDeclaration))?.get(key);
|
|
1160
|
+
if (cached !== undefined) {
|
|
1161
|
+
for (const tracked of cached.trackedSymbols)
|
|
1162
|
+
this.trackSymbol(tracked.symbol, tracked.enclosingDeclaration, tracked.meaning);
|
|
1163
|
+
if (cached.truncating) this.truncating = true;
|
|
1164
|
+
this.approximateLength += cached.addedLength;
|
|
1165
|
+
return this.deepCloneNode(cached.node);
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
let depth = 0;
|
|
1169
|
+
if (id !== undefined) {
|
|
1170
|
+
depth = this.symbolDepth.get(id) ?? 0;
|
|
1171
|
+
if (depth > 10) return this.createElidedInformationPlaceholder();
|
|
1172
|
+
this.symbolDepth.set(id, depth + 1);
|
|
1173
|
+
}
|
|
1174
|
+
this.visitedTypes.add(typeId);
|
|
1175
|
+
const prevTrackedSymbols = this.trackedSymbols;
|
|
1176
|
+
this.trackedSymbols = [];
|
|
1177
|
+
const startLength = this.approximateLength;
|
|
1178
|
+
let result: Node | undefined;
|
|
1179
|
+
switch (transform) {
|
|
1180
|
+
case TransformKind.TypeReference:
|
|
1181
|
+
result = this.typeReferenceToTypeNode(t as TypeReference);
|
|
1182
|
+
break;
|
|
1183
|
+
case TransformKind.Conditional:
|
|
1184
|
+
result = this.conditionalTypeToTypeNode(t as ConditionalType);
|
|
1185
|
+
break;
|
|
1186
|
+
case TransformKind.ObjectType:
|
|
1187
|
+
result = this.createTypeNodeFromObjectType(t);
|
|
1188
|
+
break;
|
|
1189
|
+
default:
|
|
1190
|
+
result = this.typeToTypeNode(t);
|
|
1191
|
+
break;
|
|
1192
|
+
}
|
|
1193
|
+
const addedLength = this.approximateLength - startLength;
|
|
1194
|
+
if (
|
|
1195
|
+
this.enclosingDeclaration !== undefined &&
|
|
1196
|
+
!this.reportedDiagnostic &&
|
|
1197
|
+
!this.encounteredError &&
|
|
1198
|
+
result !== undefined
|
|
1199
|
+
) {
|
|
1200
|
+
const enclosingId = getNodeId(this.enclosingDeclaration);
|
|
1201
|
+
let entries = this.serializedTypes.get(enclosingId);
|
|
1202
|
+
if (entries === undefined) {
|
|
1203
|
+
entries = new Map<string, SerializedTypeEntry>();
|
|
1204
|
+
this.serializedTypes.set(enclosingId, entries);
|
|
1205
|
+
}
|
|
1206
|
+
entries.set(key, new SerializedTypeEntry(result, this.truncating, addedLength, this.trackedSymbols));
|
|
1207
|
+
}
|
|
1208
|
+
this.visitedTypes.delete(typeId);
|
|
1209
|
+
if (id !== undefined) this.symbolDepth.set(id, depth);
|
|
1210
|
+
this.trackedSymbols = prevTrackedSymbols;
|
|
1211
|
+
return result;
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
private typeToTypeNodeOrCircularityElision(t: Type): Node | undefined {
|
|
1215
|
+
if ((t.flags & TypeFlags.Union) !== 0) {
|
|
1216
|
+
if (this.visitedTypes.has(t.id)) {
|
|
1217
|
+
if ((this.flags & NodeBuilderFlags.AllowAnonymousIdentifier) === 0) {
|
|
1218
|
+
this.encounteredError = true;
|
|
1219
|
+
this.tracker.reportCyclicStructureError();
|
|
1220
|
+
}
|
|
1221
|
+
return this.createElidedInformationPlaceholder();
|
|
1222
|
+
}
|
|
1223
|
+
return this.visitAndTransformType(t, TransformKind.Type);
|
|
1224
|
+
}
|
|
1225
|
+
return this.typeToTypeNode(t);
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
private conditionalTypeToTypeNode(t: ConditionalType): Node | undefined {
|
|
1229
|
+
const c = this.c;
|
|
1230
|
+
if (this.checkTruncationLength()) return this.createElidedInformationPlaceholder();
|
|
1231
|
+
const checkTypeNode = this.typeToTypeNode(t.checkType)!;
|
|
1232
|
+
this.approximateLength += 15;
|
|
1233
|
+
const root = t.root;
|
|
1234
|
+
const node = root.node as ConditionalTypeNode;
|
|
1235
|
+
if (
|
|
1236
|
+
(this.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams) !== 0 &&
|
|
1237
|
+
root.isDistributive &&
|
|
1238
|
+
(t.checkType.flags & TypeFlags.TypeParameter) === 0
|
|
1239
|
+
) {
|
|
1240
|
+
// `checkType extends infer T ? T extends checkType ? T extends extendsType<T> ? trueType<T> :
|
|
1241
|
+
// falseType<T> : never : never` keeps the conditional distributive over a non-parameter.
|
|
1242
|
+
const newParam = c.newTypeParameter(c.newSymbol(SymbolFlags.TypeParameter, 'T'));
|
|
1243
|
+
const name = this.typeParameterToName(newParam);
|
|
1244
|
+
const newTypeVariable = this.typeReference(name, undefined) as TypeReferenceNode;
|
|
1245
|
+
this.approximateLength += 37;
|
|
1246
|
+
const newMapper = prependTypeMapping(root.checkType, newParam, t.mapper);
|
|
1247
|
+
const saveInferTypeParameters = this.inferTypeParameters;
|
|
1248
|
+
this.inferTypeParameters = root.inferTypeParameters;
|
|
1249
|
+
const extendsTypeNode = this.typeToTypeNode(instantiateType(c, root.extendsType, newMapper))!;
|
|
1250
|
+
this.inferTypeParameters = saveInferTypeParameters;
|
|
1251
|
+
const trueTypeNode = this.typeToTypeNodeOrCircularityElision(
|
|
1252
|
+
instantiateType(c, this.getTypeFromTypeNode(node.trueType, false)!, newMapper),
|
|
1253
|
+
)!;
|
|
1254
|
+
const falseTypeNode = this.typeToTypeNodeOrCircularityElision(
|
|
1255
|
+
instantiateType(c, this.getTypeFromTypeNode(node.falseType, false)!, newMapper),
|
|
1256
|
+
)!;
|
|
1257
|
+
const newId = this.factory.cloneIdentifier(newTypeVariable.typeName as Identifier);
|
|
1258
|
+
const syntheticExtendsNode = this.created(
|
|
1259
|
+
new InferTypeNode(
|
|
1260
|
+
this.created(new TypeParameterDeclaration(undefined, newId, undefined, undefined, undefined)),
|
|
1261
|
+
),
|
|
1262
|
+
);
|
|
1263
|
+
const innerCheckConditionalNode = this.created(
|
|
1264
|
+
new ConditionalTypeNode(newTypeVariable, extendsTypeNode, trueTypeNode, falseTypeNode),
|
|
1265
|
+
);
|
|
1266
|
+
const syntheticTrueNode = this.created(
|
|
1267
|
+
new ConditionalTypeNode(
|
|
1268
|
+
this.typeReference(this.factory.cloneIdentifier(name), undefined),
|
|
1269
|
+
checkTypeNode.deepClone(),
|
|
1270
|
+
innerCheckConditionalNode,
|
|
1271
|
+
this.keyword(SyntaxKind.NeverKeyword),
|
|
1272
|
+
),
|
|
1273
|
+
);
|
|
1274
|
+
return this.created(
|
|
1275
|
+
new ConditionalTypeNode(
|
|
1276
|
+
checkTypeNode,
|
|
1277
|
+
syntheticExtendsNode,
|
|
1278
|
+
syntheticTrueNode,
|
|
1279
|
+
this.keyword(SyntaxKind.NeverKeyword),
|
|
1280
|
+
),
|
|
1281
|
+
);
|
|
1282
|
+
}
|
|
1283
|
+
const saveInferTypeParameters = this.inferTypeParameters;
|
|
1284
|
+
this.inferTypeParameters = root.inferTypeParameters;
|
|
1285
|
+
const extendsTypeNode = this.typeToTypeNode(t.extendsType)!;
|
|
1286
|
+
this.inferTypeParameters = saveInferTypeParameters;
|
|
1287
|
+
const trueTypeNode = this.typeToTypeNodeOrCircularityElision(getTrueTypeFromConditionalType(c, t))!;
|
|
1288
|
+
const falseTypeNode = this.typeToTypeNodeOrCircularityElision(getFalseTypeFromConditionalType(c, t))!;
|
|
1289
|
+
return this.created(new ConditionalTypeNode(checkTypeNode, extendsTypeNode, trueTypeNode, falseTypeNode));
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
private getParentSymbolOfTypeParameter(typeParameter: Type): Symbol | undefined {
|
|
1293
|
+
const tp = getDeclarationOfKind(typeParameter.symbol!, SyntaxKind.TypeParameter);
|
|
1294
|
+
const host = tp?.parent;
|
|
1295
|
+
if (host === undefined) return undefined;
|
|
1296
|
+
return getSymbolOfDeclaration(this.c, host);
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
private typeReferenceToTypeNode(t: TypeReference): Node | undefined {
|
|
1300
|
+
const c = this.c;
|
|
1301
|
+
let typeArguments = getTypeArguments(c, t);
|
|
1302
|
+
const target = t.target!;
|
|
1303
|
+
if (target === c.globalArrayType || target === c.globalReadonlyArrayType) {
|
|
1304
|
+
if ((this.flags & NodeBuilderFlags.WriteArrayAsGenericType) !== 0) {
|
|
1305
|
+
const typeArgumentNode = this.typeToTypeNode(typeArguments[0]!)!;
|
|
1306
|
+
return this.typeReference(
|
|
1307
|
+
this.identifier(target === c.globalArrayType ? 'Array' : 'ReadonlyArray'),
|
|
1308
|
+
this.list([typeArgumentNode]),
|
|
1309
|
+
);
|
|
1310
|
+
}
|
|
1311
|
+
const elementType = this.typeToTypeNode(typeArguments[0]!)!;
|
|
1312
|
+
const arrayType = this.created(new ArrayTypeNode(elementType));
|
|
1313
|
+
return target === c.globalArrayType
|
|
1314
|
+
? arrayType
|
|
1315
|
+
: this.created(new TypeOperatorNode(SyntaxKind.ReadonlyKeyword, arrayType));
|
|
1316
|
+
}
|
|
1317
|
+
if ((target.objectFlags & ObjectFlags.Tuple) !== 0) {
|
|
1318
|
+
const tuple = target as TupleType;
|
|
1319
|
+
const elementInfos = tuple.elementInfos;
|
|
1320
|
+
const elementTypes: Type[] = [];
|
|
1321
|
+
for (let i = 0; i < typeArguments.length; i++)
|
|
1322
|
+
elementTypes.push(
|
|
1323
|
+
removeMissingType(
|
|
1324
|
+
c,
|
|
1325
|
+
typeArguments[i]!,
|
|
1326
|
+
i < elementInfos.length && (elementInfos[i]!.flags & ElementFlags.Optional) !== 0,
|
|
1327
|
+
),
|
|
1328
|
+
);
|
|
1329
|
+
typeArguments = elementTypes;
|
|
1330
|
+
if (typeArguments.length > 0) {
|
|
1331
|
+
const arity = getTypeReferenceArity(t);
|
|
1332
|
+
const nodes = this.mapToTypeNodes(typeArguments.slice(0, arity), false);
|
|
1333
|
+
if (nodes !== undefined) {
|
|
1334
|
+
const elements = nodes.nodes;
|
|
1335
|
+
for (let i = 0; i < elements.length; i++) {
|
|
1336
|
+
const flags = elementInfos[i].flags;
|
|
1337
|
+
const labeledDeclaration = elementInfos[i].labeledDeclaration;
|
|
1338
|
+
const element = elements[i]!;
|
|
1339
|
+
if (labeledDeclaration !== undefined)
|
|
1340
|
+
elements[i] = this.created(
|
|
1341
|
+
new NamedTupleMember(
|
|
1342
|
+
(flags & ElementFlags.Variable) !== 0 ? this.token(SyntaxKind.DotDotDotToken) : undefined,
|
|
1343
|
+
this.identifier(getTupleElementLabel(c, elementInfos[i].flags, labeledDeclaration, undefined, i)),
|
|
1344
|
+
(flags & ElementFlags.Optional) !== 0 ? this.token(SyntaxKind.QuestionToken) : undefined,
|
|
1345
|
+
(flags & ElementFlags.Rest) !== 0 ? this.created(new ArrayTypeNode(element)) : element,
|
|
1346
|
+
),
|
|
1347
|
+
);
|
|
1348
|
+
else if ((flags & ElementFlags.Variable) !== 0)
|
|
1349
|
+
elements[i] = this.created(
|
|
1350
|
+
new RestTypeNode(
|
|
1351
|
+
(flags & ElementFlags.Rest) !== 0 ? this.created(new ArrayTypeNode(element)) : element,
|
|
1352
|
+
),
|
|
1353
|
+
);
|
|
1354
|
+
else if ((flags & ElementFlags.Optional) !== 0) elements[i] = this.created(new OptionalTypeNode(element));
|
|
1355
|
+
}
|
|
1356
|
+
const tupleTypeNode = this.created(new TupleTypeNode(nodes));
|
|
1357
|
+
this.context.setEmitFlags(tupleTypeNode, EmitFlags.SingleLine);
|
|
1358
|
+
return tuple.readonly
|
|
1359
|
+
? this.created(new TypeOperatorNode(SyntaxKind.ReadonlyKeyword, tupleTypeNode))
|
|
1360
|
+
: tupleTypeNode;
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
if (this.encounteredError || (this.flags & NodeBuilderFlags.AllowEmptyTuple) !== 0) {
|
|
1364
|
+
const tupleTypeNode = this.created(new TupleTypeNode(this.list([])));
|
|
1365
|
+
this.context.setEmitFlags(tupleTypeNode, EmitFlags.SingleLine);
|
|
1366
|
+
return tuple.readonly
|
|
1367
|
+
? this.created(new TypeOperatorNode(SyntaxKind.ReadonlyKeyword, tupleTypeNode))
|
|
1368
|
+
: tupleTypeNode;
|
|
1369
|
+
}
|
|
1370
|
+
this.encounteredError = true;
|
|
1371
|
+
return undefined;
|
|
1372
|
+
}
|
|
1373
|
+
const symbol = t.symbol!;
|
|
1374
|
+
if (
|
|
1375
|
+
(this.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral) !== 0 &&
|
|
1376
|
+
symbol.valueDeclaration !== undefined &&
|
|
1377
|
+
isClassLike(symbol.valueDeclaration) &&
|
|
1378
|
+
!isValueSymbolAccessible(c, symbol, this.enclosingDeclaration)
|
|
1379
|
+
)
|
|
1380
|
+
return this.createAnonymousTypeNode(t, false, false);
|
|
1381
|
+
const interfaceTarget = target as InterfaceType;
|
|
1382
|
+
const outerTypeParameters = interfaceTarget.outerTypeParameters();
|
|
1383
|
+
let i = 0;
|
|
1384
|
+
let resultType: Node | undefined = undefined;
|
|
1385
|
+
const length = outerTypeParameters.length;
|
|
1386
|
+
while (i < length) {
|
|
1387
|
+
// A group of type arguments for type parameters of one declaring container.
|
|
1388
|
+
const start = i;
|
|
1389
|
+
const parent = this.getParentSymbolOfTypeParameter(outerTypeParameters[i]!);
|
|
1390
|
+
do i++;
|
|
1391
|
+
while (i < length && this.getParentSymbolOfTypeParameter(outerTypeParameters[i]!) === parent);
|
|
1392
|
+
// A group of its own type parameters (the default outer type arguments) isn't written.
|
|
1393
|
+
let same = true;
|
|
1394
|
+
for (let k = start; k < i; k++) if (outerTypeParameters[k] !== typeArguments[k]) same = false;
|
|
1395
|
+
if (same) continue;
|
|
1396
|
+
const typeArgumentSlice = this.mapToTypeNodes(typeArguments.slice(start, i), false);
|
|
1397
|
+
const savedFlags = this.flags;
|
|
1398
|
+
this.flags |= NodeBuilderFlags.ForbidIndexedAccessSymbolReferences;
|
|
1399
|
+
const ref = symbolToTypeNode(this, parent!, SymbolFlags.Type, typeArgumentSlice);
|
|
1400
|
+
this.flags = savedFlags;
|
|
1401
|
+
if (ref !== undefined) resultType = resultType === undefined ? ref : appendReferenceToType(this, resultType, ref);
|
|
1402
|
+
}
|
|
1403
|
+
let typeArgumentNodes: NodeList | undefined = undefined;
|
|
1404
|
+
if (typeArguments.length > 0) {
|
|
1405
|
+
const typeParameters = interfaceTarget.typeParameters();
|
|
1406
|
+
let typeParameterCount = Math.min(typeParameters.length, typeArguments.length);
|
|
1407
|
+
// Iterable types elide type arguments equal to their defaults, for backwards compatible
|
|
1408
|
+
// declaration emit since they gained type parameters.
|
|
1409
|
+
if (
|
|
1410
|
+
isReferenceToType(t, getGlobalIterableType(c, false)) ||
|
|
1411
|
+
isReferenceToType(t, getGlobalIterableIteratorType(c, false)) ||
|
|
1412
|
+
isReferenceToType(t, getGlobalIterableType(c, true)) ||
|
|
1413
|
+
isReferenceToType(t, getGlobalIterableIteratorType(c, true))
|
|
1414
|
+
) {
|
|
1415
|
+
const node = t.node;
|
|
1416
|
+
const written =
|
|
1417
|
+
node instanceof TypeReferenceNode && node.typeArguments !== undefined ? node.typeArguments.nodes.length : -1;
|
|
1418
|
+
if (written < typeParameterCount)
|
|
1419
|
+
while (typeParameterCount > 0) {
|
|
1420
|
+
const typeArgument = typeArguments[typeParameterCount - 1]!;
|
|
1421
|
+
const defaultType = getDefaultFromTypeParameter(c, typeParameters[typeParameterCount - 1]!);
|
|
1422
|
+
if (defaultType === undefined || !isTypeIdenticalTo(c, typeArgument, defaultType)) break;
|
|
1423
|
+
typeParameterCount--;
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
typeArgumentNodes = this.mapToTypeNodes(typeArguments.slice(i, Math.max(i, typeParameterCount)), false);
|
|
1427
|
+
}
|
|
1428
|
+
const savedFlags = this.flags;
|
|
1429
|
+
this.flags |= NodeBuilderFlags.ForbidIndexedAccessSymbolReferences;
|
|
1430
|
+
const finalRef = symbolToTypeNode(this, symbol, SymbolFlags.Type, typeArgumentNodes);
|
|
1431
|
+
this.flags = savedFlags;
|
|
1432
|
+
if (resultType === undefined) return finalRef;
|
|
1433
|
+
return finalRef === undefined ? resultType : appendReferenceToType(this, resultType, finalRef);
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
// ---- Object types
|
|
1437
|
+
|
|
1438
|
+
private shouldWriteTypeOfFunctionSymbol(symbol: Symbol, typeId: number): Symbol | undefined {
|
|
1439
|
+
const c = this.c;
|
|
1440
|
+
let isStaticMethodSymbol = false;
|
|
1441
|
+
if ((symbol.flags & SymbolFlags.Method) !== 0)
|
|
1442
|
+
for (const d of getDeclarations(symbol))
|
|
1443
|
+
if (isStatic(d) && !hasLateBindableIndexSignature(c, d)) isStaticMethodSymbol = true;
|
|
1444
|
+
let isNonLocalFunctionSymbol = false;
|
|
1445
|
+
let isFunctionExpressionSymbol = false;
|
|
1446
|
+
if ((symbol.flags & SymbolFlags.Function) !== 0) {
|
|
1447
|
+
if (symbol.parent !== undefined) isNonLocalFunctionSymbol = true;
|
|
1448
|
+
else
|
|
1449
|
+
for (const d of getDeclarations(symbol)) {
|
|
1450
|
+
const parent = d.parent!;
|
|
1451
|
+
if (parent.kind === SyntaxKind.SourceFile || parent.kind === SyntaxKind.ModuleBlock) {
|
|
1452
|
+
isNonLocalFunctionSymbol = true;
|
|
1453
|
+
break;
|
|
1454
|
+
}
|
|
1455
|
+
const statement = parent.parent?.parent;
|
|
1456
|
+
const container = statement?.parent;
|
|
1457
|
+
if (
|
|
1458
|
+
(d.kind === SyntaxKind.FunctionExpression || d.kind === SyntaxKind.ArrowFunction) &&
|
|
1459
|
+
parent.kind === SyntaxKind.VariableDeclaration &&
|
|
1460
|
+
parent.parent!.kind === SyntaxKind.VariableDeclarationList &&
|
|
1461
|
+
statement !== undefined &&
|
|
1462
|
+
statement.kind === SyntaxKind.VariableStatement &&
|
|
1463
|
+
container !== undefined &&
|
|
1464
|
+
(container.kind === SyntaxKind.SourceFile || container.kind === SyntaxKind.ModuleBlock)
|
|
1465
|
+
) {
|
|
1466
|
+
isNonLocalFunctionSymbol = true;
|
|
1467
|
+
isFunctionExpressionSymbol = true;
|
|
1468
|
+
break;
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
if (!isStaticMethodSymbol && !isNonLocalFunctionSymbol) return undefined;
|
|
1473
|
+
let named = symbol;
|
|
1474
|
+
const valueDeclaration = symbol.valueDeclaration;
|
|
1475
|
+
if (
|
|
1476
|
+
isFunctionExpressionSymbol &&
|
|
1477
|
+
valueDeclaration !== undefined &&
|
|
1478
|
+
valueDeclaration.parent !== undefined &&
|
|
1479
|
+
valueDeclaration.parent !== this.enclosingDeclaration
|
|
1480
|
+
) {
|
|
1481
|
+
const variable = getSymbol(valueDeclaration.parent);
|
|
1482
|
+
if (variable !== undefined) named = getMergedSymbol(c, variable);
|
|
1483
|
+
}
|
|
1484
|
+
// `typeof f` is allowed for static and non-local functions, or a function referring to itself,
|
|
1485
|
+
// when it can be named or there's no structural fallback.
|
|
1486
|
+
if (
|
|
1487
|
+
((this.flags & NodeBuilderFlags.UseTypeOfFunction) !== 0 || this.visitedTypes.has(typeId)) &&
|
|
1488
|
+
((this.flags & NodeBuilderFlags.UseStructuralFallback) === 0 ||
|
|
1489
|
+
isValueSymbolAccessible(c, named, this.enclosingDeclaration))
|
|
1490
|
+
)
|
|
1491
|
+
return named;
|
|
1492
|
+
return undefined;
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
/** The symbol to write `typeof` of for an anonymous type, if any. */
|
|
1496
|
+
private shouldEmitTypeOfSymbol(
|
|
1497
|
+
forceExpansion: boolean,
|
|
1498
|
+
forceClassExpansion: boolean,
|
|
1499
|
+
isInstanceType: SymbolFlags,
|
|
1500
|
+
symbol: Symbol,
|
|
1501
|
+
typeId: number,
|
|
1502
|
+
): Symbol | undefined {
|
|
1503
|
+
if (forceExpansion) return undefined;
|
|
1504
|
+
const c = this.c;
|
|
1505
|
+
const valueDeclaration = symbol.valueDeclaration;
|
|
1506
|
+
if (
|
|
1507
|
+
((symbol.flags & SymbolFlags.Class) !== 0 &&
|
|
1508
|
+
!forceClassExpansion &&
|
|
1509
|
+
getBaseTypeVariableOfClass(c, symbol) === undefined &&
|
|
1510
|
+
!(
|
|
1511
|
+
valueDeclaration !== undefined &&
|
|
1512
|
+
isClassLike(valueDeclaration) &&
|
|
1513
|
+
(this.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral) !== 0 &&
|
|
1514
|
+
(valueDeclaration.kind !== SyntaxKind.ClassDeclaration ||
|
|
1515
|
+
isSymbolAccessible(c, symbol, this.enclosingDeclaration, isInstanceType, false).accessibility !==
|
|
1516
|
+
SymbolAccessibility.Accessible)
|
|
1517
|
+
)) ||
|
|
1518
|
+
(symbol.flags & (SymbolFlags.Enum | SymbolFlags.ValueModule)) !== 0
|
|
1519
|
+
)
|
|
1520
|
+
return symbol;
|
|
1521
|
+
return this.shouldWriteTypeOfFunctionSymbol(symbol, typeId);
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
createAnonymousTypeNode(t: Type, forceClassExpansion: boolean, forceExpansion: boolean): Node | undefined {
|
|
1525
|
+
const c = this.c;
|
|
1526
|
+
const typeId = t.id;
|
|
1527
|
+
const symbol = t.symbol;
|
|
1528
|
+
// Anonymous types without a symbol are never circular.
|
|
1529
|
+
if (symbol === undefined) return this.createTypeNodeFromObjectType(t);
|
|
1530
|
+
if ((t.objectFlags & ObjectFlags.InstantiationExpressionType) !== 0) {
|
|
1531
|
+
const existing = (t as InstantiationExpressionType).node;
|
|
1532
|
+
// The node is unreliable for members of unions and intersections, so it's checked.
|
|
1533
|
+
if (
|
|
1534
|
+
existing !== undefined &&
|
|
1535
|
+
existing.kind === SyntaxKind.TypeQuery &&
|
|
1536
|
+
this.getTypeFromTypeNode(existing, false) === t
|
|
1537
|
+
) {
|
|
1538
|
+
if (this.visitedTypes.has(typeId)) return this.createElidedInformationPlaceholder();
|
|
1539
|
+
this.visitedTypes.add(typeId);
|
|
1540
|
+
const typeNode = this.tryReuseExistingNonParameterTypeNode(existing, t, undefined, undefined);
|
|
1541
|
+
this.visitedTypes.delete(typeId);
|
|
1542
|
+
if (typeNode !== undefined) return typeNode;
|
|
1543
|
+
}
|
|
1544
|
+
if (this.visitedTypes.has(typeId)) return this.createElidedInformationPlaceholder();
|
|
1545
|
+
return this.visitAndTransformType(t, TransformKind.ObjectType);
|
|
1546
|
+
}
|
|
1547
|
+
const isInstanceType = isClassInstanceSide(c, t) ? SymbolFlags.Type : SymbolFlags.Value;
|
|
1548
|
+
const typeOfSymbol = this.shouldEmitTypeOfSymbol(
|
|
1549
|
+
forceExpansion,
|
|
1550
|
+
forceClassExpansion,
|
|
1551
|
+
isInstanceType,
|
|
1552
|
+
symbol,
|
|
1553
|
+
typeId,
|
|
1554
|
+
);
|
|
1555
|
+
if (typeOfSymbol !== undefined) return symbolToTypeNode(this, typeOfSymbol, isInstanceType, undefined);
|
|
1556
|
+
if (this.visitedTypes.has(typeId)) {
|
|
1557
|
+
// An anonymous type literal in a type alias is written as the alias.
|
|
1558
|
+
const typeAlias = getTypeAliasForTypeLiteral(c, t);
|
|
1559
|
+
if (typeAlias !== undefined) return symbolToTypeNode(this, typeAlias, SymbolFlags.Type, undefined);
|
|
1560
|
+
return this.createElidedInformationPlaceholder();
|
|
1561
|
+
}
|
|
1562
|
+
return this.visitAndTransformType(t, TransformKind.ObjectType);
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
createTypeNodeFromObjectType(t: Type): Node | undefined {
|
|
1566
|
+
const c = this.c;
|
|
1567
|
+
if (
|
|
1568
|
+
isGenericMappedType(c, t) ||
|
|
1569
|
+
((t.objectFlags & ObjectFlags.Mapped) !== 0 && sideOf(c, t as MappedType).containsError)
|
|
1570
|
+
)
|
|
1571
|
+
return this.createMappedTypeNodeFromType(t as MappedType);
|
|
1572
|
+
const resolved = resolveStructuredTypeMembers(c, t);
|
|
1573
|
+
const callSignatures = resolved.callSignatures;
|
|
1574
|
+
const constructSignatures = resolved.constructSignatures;
|
|
1575
|
+
if (resolved.properties.length === 0 && resolved.indexInfos.length === 0) {
|
|
1576
|
+
if (callSignatures.length === 0 && constructSignatures.length === 0) {
|
|
1577
|
+
this.approximateLength += 2;
|
|
1578
|
+
const result = this.created(new TypeLiteralNode(this.list([])));
|
|
1579
|
+
this.context.setEmitFlags(result, EmitFlags.SingleLine);
|
|
1580
|
+
return result;
|
|
1581
|
+
}
|
|
1582
|
+
if (callSignatures.length === 1 && constructSignatures.length === 0)
|
|
1583
|
+
return this.signatureToSignatureDeclaration(callSignatures[0]!, SyntaxKind.FunctionType, undefined);
|
|
1584
|
+
if (constructSignatures.length === 1 && callSignatures.length === 0)
|
|
1585
|
+
return this.signatureToSignatureDeclaration(constructSignatures[0]!, SyntaxKind.ConstructorType, undefined);
|
|
1586
|
+
}
|
|
1587
|
+
const abstractSignatures = constructSignatures.filter((s) => (s.flags & SignatureFlags.Abstract) !== 0);
|
|
1588
|
+
if (abstractSignatures.length > 0) {
|
|
1589
|
+
const types: Type[] = [];
|
|
1590
|
+
for (const s of abstractSignatures) types.push(getOrCreateTypeFromSignature(c, s));
|
|
1591
|
+
// Type elements other than abstract construct signatures.
|
|
1592
|
+
let propertyCount = resolved.properties.length;
|
|
1593
|
+
if ((this.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral) !== 0) {
|
|
1594
|
+
propertyCount = 0;
|
|
1595
|
+
for (const p of resolved.properties) if ((p.flags & SymbolFlags.Prototype) === 0) propertyCount++;
|
|
1596
|
+
}
|
|
1597
|
+
const typeElementCount =
|
|
1598
|
+
callSignatures.length +
|
|
1599
|
+
(constructSignatures.length - abstractSignatures.length) +
|
|
1600
|
+
resolved.indexInfos.length +
|
|
1601
|
+
propertyCount;
|
|
1602
|
+
// `abstract class C {}` is `abstract new () => C`, not `(abstract new () => C) & {}`.
|
|
1603
|
+
if (typeElementCount !== 0) types.push(getResolvedTypeWithoutAbstractConstructSignatures(c, t, resolved));
|
|
1604
|
+
return this.typeToTypeNode(getIntersectionType(c, types));
|
|
1605
|
+
}
|
|
1606
|
+
const savedFlags = this.flags;
|
|
1607
|
+
this.flags |= NodeBuilderFlags.InObjectTypeLiteral;
|
|
1608
|
+
const members = this.createTypeNodesFromResolvedType(t, resolved);
|
|
1609
|
+
this.flags = savedFlags;
|
|
1610
|
+
const typeLiteralNode = this.created(new TypeLiteralNode(members ?? this.list([])));
|
|
1611
|
+
this.approximateLength += 2;
|
|
1612
|
+
this.context.setEmitFlags(
|
|
1613
|
+
typeLiteralNode,
|
|
1614
|
+
(this.flags & NodeBuilderFlags.MultilineObjectLiterals) !== 0 ? EmitFlags.None : EmitFlags.SingleLine,
|
|
1615
|
+
);
|
|
1616
|
+
return typeLiteralNode;
|
|
1617
|
+
}
|
|
1618
|
+
|
|
1619
|
+
/** The type elements of `t`, whose members are `resolved`. */
|
|
1620
|
+
private createTypeNodesFromResolvedType(t: Type, resolved: StructuredType): NodeList | undefined {
|
|
1621
|
+
if (this.checkTruncationLength()) {
|
|
1622
|
+
if ((this.flags & NodeBuilderFlags.NoTruncation) !== 0) {
|
|
1623
|
+
const element = this.created(new NotEmittedTypeElement());
|
|
1624
|
+
this.context.addSyntheticTrailingComment(element, SyntaxKind.MultiLineCommentTrivia, 'elided', false);
|
|
1625
|
+
return this.list([element]);
|
|
1626
|
+
}
|
|
1627
|
+
return this.list([
|
|
1628
|
+
this.created(
|
|
1629
|
+
new PropertySignatureDeclaration(undefined, this.identifier('...'), undefined, undefined, undefined),
|
|
1630
|
+
),
|
|
1631
|
+
]);
|
|
1632
|
+
}
|
|
1633
|
+
const typeElements: Node[] = [];
|
|
1634
|
+
for (const signature of resolved.callSignatures)
|
|
1635
|
+
typeElements.push(this.signatureToSignatureDeclaration(signature, SyntaxKind.CallSignature, undefined));
|
|
1636
|
+
for (const signature of resolved.constructSignatures) {
|
|
1637
|
+
if ((signature.flags & SignatureFlags.Abstract) !== 0) continue;
|
|
1638
|
+
typeElements.push(this.signatureToSignatureDeclaration(signature, SyntaxKind.ConstructSignature, undefined));
|
|
1639
|
+
}
|
|
1640
|
+
for (const info of resolved.indexInfos) {
|
|
1641
|
+
// tsgo creates the placeholder for every index signature, and its length counts toward truncation.
|
|
1642
|
+
const placeholder = this.createElidedInformationPlaceholder();
|
|
1643
|
+
const typeNode = (t.objectFlags & ObjectFlags.ReverseMapped) !== 0 ? placeholder : undefined;
|
|
1644
|
+
for (const element of this.indexInfoToObjectComputedNamesOrSignatureDeclaration(info, typeNode))
|
|
1645
|
+
typeElements.push(element);
|
|
1646
|
+
}
|
|
1647
|
+
const properties = resolved.properties;
|
|
1648
|
+
if (properties.length === 0) return this.list(typeElements);
|
|
1649
|
+
let i = 0;
|
|
1650
|
+
for (const propertySymbol of properties) {
|
|
1651
|
+
i++;
|
|
1652
|
+
if ((this.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral) !== 0) {
|
|
1653
|
+
if ((propertySymbol.flags & SymbolFlags.Prototype) !== 0) continue;
|
|
1654
|
+
if (
|
|
1655
|
+
(getDeclarationModifierFlagsFromSymbol(this.c, propertySymbol, false) &
|
|
1656
|
+
(ModifierFlags.Private | ModifierFlags.Protected)) !==
|
|
1657
|
+
0
|
|
1658
|
+
)
|
|
1659
|
+
this.tracker.reportPrivateInBaseOfClassExpression(propertySymbol.name);
|
|
1660
|
+
if (isPrivateIdentifierSymbol(propertySymbol))
|
|
1661
|
+
this.tracker.reportPrivateInBaseOfClassExpression(symbolName(propertySymbol));
|
|
1662
|
+
}
|
|
1663
|
+
if (this.checkTruncationLength() && i + 2 < properties.length - 1) {
|
|
1664
|
+
if ((this.flags & NodeBuilderFlags.NoTruncation) !== 0) {
|
|
1665
|
+
if (typeElements.length > 0)
|
|
1666
|
+
this.context.addSyntheticTrailingComment(
|
|
1667
|
+
typeElements[typeElements.length - 1]!,
|
|
1668
|
+
SyntaxKind.MultiLineCommentTrivia,
|
|
1669
|
+
'... ' + (properties.length - i) + ' more elided ...',
|
|
1670
|
+
false,
|
|
1671
|
+
);
|
|
1672
|
+
} else
|
|
1673
|
+
typeElements.push(
|
|
1674
|
+
this.created(
|
|
1675
|
+
new PropertySignatureDeclaration(
|
|
1676
|
+
undefined,
|
|
1677
|
+
this.identifier('... ' + (properties.length - i) + ' more ...'),
|
|
1678
|
+
undefined,
|
|
1679
|
+
undefined,
|
|
1680
|
+
undefined,
|
|
1681
|
+
),
|
|
1682
|
+
),
|
|
1683
|
+
);
|
|
1684
|
+
this.addPropertyToElementList(properties[properties.length - 1]!, typeElements);
|
|
1685
|
+
break;
|
|
1686
|
+
}
|
|
1687
|
+
this.addPropertyToElementList(propertySymbol, typeElements);
|
|
1688
|
+
}
|
|
1689
|
+
return typeElements.length !== 0 ? this.list(typeElements) : undefined;
|
|
1690
|
+
}
|
|
1691
|
+
|
|
1692
|
+
private shouldUsePlaceholderForProperty(propertySymbol: Symbol): boolean {
|
|
1693
|
+
// Placeholders for reverse mapped types (1) already being written, (2) nested in a mapping
|
|
1694
|
+
// over a non-anonymous type, or (3) nested deeply in the same mapped type.
|
|
1695
|
+
if ((propertySymbol.checkFlags & CheckFlags.ReverseMapped) === 0) return false;
|
|
1696
|
+
const stack = this.reverseMappedStack;
|
|
1697
|
+
if (stack.indexOf(propertySymbol) >= 0) return true;
|
|
1698
|
+
if (stack.length > 0) {
|
|
1699
|
+
const propertyType = this.c.symbolLinks(stack[stack.length - 1]!).reverseMappedPropertyType;
|
|
1700
|
+
if (propertyType !== undefined && (propertyType.objectFlags & ObjectFlags.Anonymous) === 0) return true;
|
|
1701
|
+
}
|
|
1702
|
+
if (stack.length < maxReverseMappedNestingInspectionDepth) return false;
|
|
1703
|
+
const propMappedType = this.c.symbolLinks(propertySymbol).reverseMappedMappedType;
|
|
1704
|
+
if (propMappedType === undefined || propMappedType.symbol === undefined) return false;
|
|
1705
|
+
for (let i = 0; i < stack.length; i++) {
|
|
1706
|
+
if (i > maxReverseMappedNestingInspectionDepth) break;
|
|
1707
|
+
const mappedType = this.c.symbolLinks(stack[stack.length - 1 - i]!).reverseMappedMappedType;
|
|
1708
|
+
if (mappedType !== undefined && mappedType.symbol === propMappedType.symbol) return true;
|
|
1709
|
+
}
|
|
1710
|
+
return false;
|
|
1711
|
+
}
|
|
1712
|
+
|
|
1713
|
+
trackComputedName(accessExpression: Node, enclosingDeclaration: Node | undefined): void {
|
|
1714
|
+
const c = this.c;
|
|
1715
|
+
const firstIdentifier = getFirstIdentifier(accessExpression);
|
|
1716
|
+
const name = resolveName(
|
|
1717
|
+
c,
|
|
1718
|
+
enclosingDeclaration,
|
|
1719
|
+
getText(firstIdentifier),
|
|
1720
|
+
SymbolFlags.Value | SymbolFlags.ExportValue,
|
|
1721
|
+
undefined,
|
|
1722
|
+
true,
|
|
1723
|
+
false,
|
|
1724
|
+
);
|
|
1725
|
+
if (name !== undefined) {
|
|
1726
|
+
this.trackSymbol(name, enclosingDeclaration, SymbolFlags.Value);
|
|
1727
|
+
return;
|
|
1728
|
+
}
|
|
1729
|
+
// Unresolved at the target: track the symbol at its own location, which is inaccessible.
|
|
1730
|
+
const fallback = resolveName(
|
|
1731
|
+
c,
|
|
1732
|
+
firstIdentifier,
|
|
1733
|
+
getText(firstIdentifier),
|
|
1734
|
+
SymbolFlags.Value | SymbolFlags.ExportValue,
|
|
1735
|
+
undefined,
|
|
1736
|
+
true,
|
|
1737
|
+
false,
|
|
1738
|
+
);
|
|
1739
|
+
if (fallback !== undefined) this.trackSymbol(fallback, enclosingDeclaration, SymbolFlags.Value);
|
|
1740
|
+
}
|
|
1741
|
+
|
|
1742
|
+
private addPropertyToElementList(propertySymbol: Symbol, typeElements: Node[]): void {
|
|
1743
|
+
const c = this.c;
|
|
1744
|
+
const propertyIsReverseMapped = (propertySymbol.checkFlags & CheckFlags.ReverseMapped) !== 0;
|
|
1745
|
+
const propertyType = this.shouldUsePlaceholderForProperty(propertySymbol)
|
|
1746
|
+
? c.anyType
|
|
1747
|
+
: getNonMissingTypeOfSymbol(c, propertySymbol);
|
|
1748
|
+
const saveEnclosingDeclaration = this.enclosingDeclaration;
|
|
1749
|
+
this.enclosingDeclaration = undefined;
|
|
1750
|
+
if (isLateBoundName(propertySymbol.name)) {
|
|
1751
|
+
if (declarationCount(propertySymbol) > 0) {
|
|
1752
|
+
const decl = propertySymbol.declaration!;
|
|
1753
|
+
if (hasLateBindableName(c, decl)) {
|
|
1754
|
+
if (decl instanceof BinaryExpression) {
|
|
1755
|
+
const name = getNameOfDeclaration(decl);
|
|
1756
|
+
if (
|
|
1757
|
+
name instanceof ElementAccessExpression &&
|
|
1758
|
+
isPropertyAccessEntityNameExpression(name.argumentExpression)
|
|
1759
|
+
)
|
|
1760
|
+
this.trackComputedName(name.argumentExpression, saveEnclosingDeclaration);
|
|
1761
|
+
} else this.trackComputedName(getExpression(getName(decl)!)!, saveEnclosingDeclaration);
|
|
1762
|
+
}
|
|
1763
|
+
} else this.tracker.reportNonSerializableProperty(symbolToString(c, propertySymbol));
|
|
1764
|
+
}
|
|
1765
|
+
this.enclosingDeclaration =
|
|
1766
|
+
propertySymbol.valueDeclaration ??
|
|
1767
|
+
(declarationCount(propertySymbol) > 0 ? propertySymbol.declaration! : saveEnclosingDeclaration);
|
|
1768
|
+
const propertyName = getPropertyNameNodeForSymbol(this, propertySymbol);
|
|
1769
|
+
this.enclosingDeclaration = saveEnclosingDeclaration;
|
|
1770
|
+
this.approximateLength += symbolName(propertySymbol).length + 1;
|
|
1771
|
+
if ((propertySymbol.flags & SymbolFlags.Accessor) !== 0) {
|
|
1772
|
+
const writeType = getWriteTypeOfSymbol(c, propertySymbol);
|
|
1773
|
+
if (!isErrorType(c, propertyType) && !isErrorType(c, writeType)) {
|
|
1774
|
+
const propDeclaration = getDeclarationOfKind(propertySymbol, SyntaxKind.PropertyDeclaration);
|
|
1775
|
+
const parentIsClass =
|
|
1776
|
+
propertySymbol.parent !== undefined && (propertySymbol.parent.flags & SymbolFlags.Class) !== 0;
|
|
1777
|
+
if (propertyType !== writeType || (parentIsClass && propDeclaration === undefined)) {
|
|
1778
|
+
const symbolMapper = c.symbolMappers.get(getSymbolId(propertySymbol));
|
|
1779
|
+
const getterDeclaration = getDeclarationOfKind(propertySymbol, SyntaxKind.GetAccessor);
|
|
1780
|
+
if (getterDeclaration !== undefined) {
|
|
1781
|
+
let getterSignature = getSignatureFromDeclaration(c, getterDeclaration);
|
|
1782
|
+
if (symbolMapper !== undefined) getterSignature = instantiateSignature(c, getterSignature, symbolMapper);
|
|
1783
|
+
const getter = this.signatureToSignatureDeclaration(
|
|
1784
|
+
getterSignature,
|
|
1785
|
+
SyntaxKind.GetAccessor,
|
|
1786
|
+
new SignatureDeclarationOptions([], propertyName, undefined),
|
|
1787
|
+
);
|
|
1788
|
+
this.setCommentRange(getter, getterDeclaration);
|
|
1789
|
+
typeElements.push(getter);
|
|
1790
|
+
}
|
|
1791
|
+
const setterDeclaration = getDeclarationOfKind(propertySymbol, SyntaxKind.SetAccessor);
|
|
1792
|
+
if (setterDeclaration !== undefined) {
|
|
1793
|
+
let setterSignature = getSignatureFromDeclaration(c, setterDeclaration);
|
|
1794
|
+
if (symbolMapper !== undefined) setterSignature = instantiateSignature(c, setterSignature, symbolMapper);
|
|
1795
|
+
const setter = this.signatureToSignatureDeclaration(
|
|
1796
|
+
setterSignature,
|
|
1797
|
+
SyntaxKind.SetAccessor,
|
|
1798
|
+
new SignatureDeclarationOptions([], propertyName, undefined),
|
|
1799
|
+
);
|
|
1800
|
+
this.setCommentRange(setter, setterDeclaration);
|
|
1801
|
+
typeElements.push(setter);
|
|
1802
|
+
}
|
|
1803
|
+
return;
|
|
1804
|
+
}
|
|
1805
|
+
if (parentIsClass && propDeclaration !== undefined && hasAccessorKeyword(propDeclaration)) {
|
|
1806
|
+
const fakeGetterSignature = c.newSignature(
|
|
1807
|
+
SignatureFlags.None,
|
|
1808
|
+
undefined,
|
|
1809
|
+
[],
|
|
1810
|
+
undefined,
|
|
1811
|
+
[],
|
|
1812
|
+
propertyType,
|
|
1813
|
+
0,
|
|
1814
|
+
);
|
|
1815
|
+
const fakeGetter = this.signatureToSignatureDeclaration(
|
|
1816
|
+
fakeGetterSignature,
|
|
1817
|
+
SyntaxKind.GetAccessor,
|
|
1818
|
+
new SignatureDeclarationOptions([], propertyName, undefined),
|
|
1819
|
+
);
|
|
1820
|
+
this.setCommentRange(fakeGetter, propDeclaration);
|
|
1821
|
+
typeElements.push(fakeGetter);
|
|
1822
|
+
const setterParam = c.newSymbol(SymbolFlags.FunctionScopedVariable, 'arg');
|
|
1823
|
+
c.symbolTypes.set(getSymbolId(setterParam), writeType);
|
|
1824
|
+
const fakeSetterSignature = c.newSignature(
|
|
1825
|
+
SignatureFlags.None,
|
|
1826
|
+
undefined,
|
|
1827
|
+
[],
|
|
1828
|
+
undefined,
|
|
1829
|
+
[setterParam],
|
|
1830
|
+
c.voidType,
|
|
1831
|
+
0,
|
|
1832
|
+
);
|
|
1833
|
+
typeElements.push(
|
|
1834
|
+
this.signatureToSignatureDeclaration(
|
|
1835
|
+
fakeSetterSignature,
|
|
1836
|
+
SyntaxKind.SetAccessor,
|
|
1837
|
+
new SignatureDeclarationOptions([], propertyName, undefined),
|
|
1838
|
+
),
|
|
1839
|
+
);
|
|
1840
|
+
return;
|
|
1841
|
+
}
|
|
1842
|
+
}
|
|
1843
|
+
}
|
|
1844
|
+
const optionalToken =
|
|
1845
|
+
(propertySymbol.flags & SymbolFlags.Optional) !== 0 ? this.token(SyntaxKind.QuestionToken) : undefined;
|
|
1846
|
+
if (
|
|
1847
|
+
(propertySymbol.flags & (SymbolFlags.Function | SymbolFlags.Method)) !== 0 &&
|
|
1848
|
+
getPropertiesOfObjectType(c, propertyType).length === 0 &&
|
|
1849
|
+
!isReadonlySymbol(c, propertySymbol)
|
|
1850
|
+
) {
|
|
1851
|
+
const signatures = getSignaturesOfType(
|
|
1852
|
+
c,
|
|
1853
|
+
filterType(c, propertyType, (u) => (u.flags & TypeFlags.Undefined) === 0),
|
|
1854
|
+
SignatureKind.Call,
|
|
1855
|
+
);
|
|
1856
|
+
for (const signature of signatures) {
|
|
1857
|
+
const methodDeclaration = this.signatureToSignatureDeclaration(
|
|
1858
|
+
signature,
|
|
1859
|
+
SyntaxKind.MethodSignature,
|
|
1860
|
+
new SignatureDeclarationOptions([], propertyName, optionalToken),
|
|
1861
|
+
);
|
|
1862
|
+
this.setCommentRange(methodDeclaration, signature.declaration ?? propertySymbol.valueDeclaration);
|
|
1863
|
+
typeElements.push(methodDeclaration);
|
|
1864
|
+
}
|
|
1865
|
+
if (signatures.length !== 0 || optionalToken === undefined) return;
|
|
1866
|
+
}
|
|
1867
|
+
let propertyTypeNode: Node;
|
|
1868
|
+
if (this.shouldUsePlaceholderForProperty(propertySymbol))
|
|
1869
|
+
propertyTypeNode = this.createElidedInformationPlaceholder();
|
|
1870
|
+
else {
|
|
1871
|
+
if (propertyIsReverseMapped) this.reverseMappedStack.push(propertySymbol);
|
|
1872
|
+
propertyTypeNode = this.serializeTypeForDeclaration(undefined, propertyType, propertySymbol, true);
|
|
1873
|
+
if (propertyIsReverseMapped) this.reverseMappedStack.pop();
|
|
1874
|
+
}
|
|
1875
|
+
let modifiers: ModifierList | undefined = undefined;
|
|
1876
|
+
if (isReadonlySymbol(c, propertySymbol)) {
|
|
1877
|
+
modifiers = this.modifierList([this.token(SyntaxKind.ReadonlyKeyword)]);
|
|
1878
|
+
this.approximateLength += 9;
|
|
1879
|
+
}
|
|
1880
|
+
const propertySignature = this.created(
|
|
1881
|
+
new PropertySignatureDeclaration(modifiers, propertyName, optionalToken, propertyTypeNode, undefined),
|
|
1882
|
+
);
|
|
1883
|
+
this.setCommentRange(propertySignature, propertySymbol.valueDeclaration);
|
|
1884
|
+
typeElements.push(propertySignature);
|
|
1885
|
+
}
|
|
1886
|
+
|
|
1887
|
+
setCommentRange(node: Node, range: Node | undefined): void {
|
|
1888
|
+
// Comments are copied only within the file being written, for declaration emit.
|
|
1889
|
+
if (range !== undefined && this.enclosingFile !== undefined && this.enclosingFile === getSourceFileOfNode(range))
|
|
1890
|
+
this.context.assignCommentRange(node, range);
|
|
1891
|
+
}
|
|
1892
|
+
|
|
1893
|
+
private isDeclaredInEnclosingFile(symbol: Symbol): boolean {
|
|
1894
|
+
for (const d of getDeclarations(symbol)) if (getSourceFileOfNode(d) === this.enclosingFile) return true;
|
|
1895
|
+
return false;
|
|
1896
|
+
}
|
|
1897
|
+
|
|
1898
|
+
private areTriviallySerializableComputedNames(components: readonly Node[]): boolean {
|
|
1899
|
+
for (const e of components) if (!this.isTriviallySerializableComputedName(e)) return false;
|
|
1900
|
+
return true;
|
|
1901
|
+
}
|
|
1902
|
+
|
|
1903
|
+
private isTriviallySerializableComputedName(e: Node): boolean {
|
|
1904
|
+
const name = getName(e);
|
|
1905
|
+
if (name === undefined || name.kind !== SyntaxKind.ComputedPropertyName) return false;
|
|
1906
|
+
const expression = getExpression(name)!;
|
|
1907
|
+
if (!isEntityNameExpression(expression, false)) return false;
|
|
1908
|
+
return (
|
|
1909
|
+
isEntityNameVisible(this.c, expression, this.enclosingDeclaration!).accessibility ===
|
|
1910
|
+
SymbolAccessibility.Accessible
|
|
1911
|
+
);
|
|
1912
|
+
}
|
|
1913
|
+
|
|
1914
|
+
private indexInfoToObjectComputedNamesOrSignatureDeclaration(
|
|
1915
|
+
indexInfo: IndexInfo,
|
|
1916
|
+
typeNode: Node | undefined,
|
|
1917
|
+
): Node[] {
|
|
1918
|
+
const components = indexInfo.components;
|
|
1919
|
+
// An index info from computed property names is written as those names when all are visible `a.b.c`.
|
|
1920
|
+
if (
|
|
1921
|
+
components.length > 0 &&
|
|
1922
|
+
this.enclosingDeclaration !== undefined &&
|
|
1923
|
+
this.areTriviallySerializableComputedNames(components)
|
|
1924
|
+
) {
|
|
1925
|
+
const results: Node[] = [];
|
|
1926
|
+
let bailed = false;
|
|
1927
|
+
for (const e of components) {
|
|
1928
|
+
// Late-bound members are written as properties anyway.
|
|
1929
|
+
if (hasLateBindableName(this.c, e)) continue;
|
|
1930
|
+
const eName = getName(e)!;
|
|
1931
|
+
const name = tryReuseExistingNode(this, eName);
|
|
1932
|
+
if (name === undefined) {
|
|
1933
|
+
bailed = true;
|
|
1934
|
+
break;
|
|
1935
|
+
}
|
|
1936
|
+
this.trackComputedName(getExpression(eName)!, this.enclosingDeclaration);
|
|
1937
|
+
const modifiers = indexInfo.isReadonly
|
|
1938
|
+
? this.modifierList([this.token(SyntaxKind.ReadonlyKeyword)])
|
|
1939
|
+
: undefined;
|
|
1940
|
+
const postfixToken = getPostfixToken(e);
|
|
1941
|
+
const signature = this.created(
|
|
1942
|
+
new PropertySignatureDeclaration(
|
|
1943
|
+
modifiers,
|
|
1944
|
+
name,
|
|
1945
|
+
postfixToken === undefined ? undefined : this.token(postfixToken.kind),
|
|
1946
|
+
typeNode !== undefined ? typeNode.deepClone() : this.typeToTypeNode(getTypeOfSymbol(this.c, getSymbol(e)!)),
|
|
1947
|
+
undefined,
|
|
1948
|
+
),
|
|
1949
|
+
);
|
|
1950
|
+
signature.pos = e.pos;
|
|
1951
|
+
signature.end = e.end;
|
|
1952
|
+
results.push(signature);
|
|
1953
|
+
}
|
|
1954
|
+
if (!bailed) return results;
|
|
1955
|
+
}
|
|
1956
|
+
return [this.indexInfoToIndexSignatureDeclaration(indexInfo, typeNode)];
|
|
1957
|
+
}
|
|
1958
|
+
|
|
1959
|
+
indexInfoToIndexSignatureDeclaration(indexInfo: IndexInfo, typeNode: Node | undefined): Node {
|
|
1960
|
+
const name = getNameFromIndexInfo(indexInfo);
|
|
1961
|
+
const indexerTypeNode = this.typeToTypeNode(indexInfo.keyType);
|
|
1962
|
+
const indexingParameter = this.created(
|
|
1963
|
+
new ParameterDeclaration(undefined, undefined, this.identifier(name), undefined, indexerTypeNode, undefined),
|
|
1964
|
+
);
|
|
1965
|
+
const valueTypeNode = typeNode ?? this.typeToTypeNode(indexInfo.valueType);
|
|
1966
|
+
this.approximateLength += name.length + 4;
|
|
1967
|
+
let modifiers: ModifierList | undefined = undefined;
|
|
1968
|
+
if (indexInfo.isReadonly) {
|
|
1969
|
+
this.approximateLength += 9;
|
|
1970
|
+
modifiers = this.modifierList([this.token(SyntaxKind.ReadonlyKeyword)]);
|
|
1971
|
+
}
|
|
1972
|
+
return this.created(new IndexSignatureDeclaration(modifiers, this.list([indexingParameter]), valueTypeNode));
|
|
1973
|
+
}
|
|
1974
|
+
|
|
1975
|
+
// ---- Mapped types
|
|
1976
|
+
|
|
1977
|
+
private isMappedTypeHomomorphic(mapped: MappedType): boolean {
|
|
1978
|
+
return getHomomorphicTypeVariable(this.c, mapped) !== undefined;
|
|
1979
|
+
}
|
|
1980
|
+
|
|
1981
|
+
private isHomomorphicMappedTypeWithNonHomomorphicInstantiation(mapped: MappedType): boolean {
|
|
1982
|
+
return (
|
|
1983
|
+
mapped.target !== undefined &&
|
|
1984
|
+
!this.isMappedTypeHomomorphic(mapped) &&
|
|
1985
|
+
this.isMappedTypeHomomorphic(mapped.target as MappedType)
|
|
1986
|
+
);
|
|
1987
|
+
}
|
|
1988
|
+
|
|
1989
|
+
private createMappedTypeNodeFromType(t: MappedType): Node | undefined {
|
|
1990
|
+
const c = this.c;
|
|
1991
|
+
const declaration = t.declaration as MappedTypeNode;
|
|
1992
|
+
const readonlyToken =
|
|
1993
|
+
declaration.readonlyToken !== undefined ? this.token(declaration.readonlyToken.kind) : undefined;
|
|
1994
|
+
const questionToken =
|
|
1995
|
+
declaration.questionToken !== undefined ? this.token(declaration.questionToken.kind) : undefined;
|
|
1996
|
+
let appropriateConstraintTypeNode: Node;
|
|
1997
|
+
let newTypeVariable: TypeReferenceNode | undefined = undefined;
|
|
1998
|
+
let templateType = getTemplateTypeFromMappedType(c, t);
|
|
1999
|
+
const typeParameter = getTypeParameterFromMappedType(c, t);
|
|
2000
|
+
const generateNames = (this.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams) !== 0;
|
|
2001
|
+
// A mapped type preserving modifiers without a `keyof` constraint needs a wrapper to keep
|
|
2002
|
+
// preserving them when inlined.
|
|
2003
|
+
const constraintType = getConstraintTypeFromMappedType(c, t);
|
|
2004
|
+
const needsModifierPreservingWrapper =
|
|
2005
|
+
!isMappedTypeWithKeyofConstraintDeclaration(c, t) &&
|
|
2006
|
+
(getModifiersTypeFromMappedType(c, t).flags & TypeFlags.Unknown) === 0 &&
|
|
2007
|
+
generateNames &&
|
|
2008
|
+
!(
|
|
2009
|
+
(constraintType.flags & TypeFlags.TypeParameter) !== 0 &&
|
|
2010
|
+
((getConstraintOfTypeParameter(c, constraintType)?.flags ?? 0) & TypeFlags.Index) !== 0
|
|
2011
|
+
);
|
|
2012
|
+
if (isMappedTypeWithKeyofConstraintDeclaration(c, t)) {
|
|
2013
|
+
// `{ [P in keyof T]: X }` keeps its `keyof`, which distribution may lose.
|
|
2014
|
+
if (generateNames && this.isHomomorphicMappedTypeWithNonHomomorphicInstantiation(t)) {
|
|
2015
|
+
const newConstraintParam = c.newTypeParameter(c.newSymbol(SymbolFlags.TypeParameter, 'T'));
|
|
2016
|
+
const name = this.typeParameterToName(newConstraintParam);
|
|
2017
|
+
const target = t.target as MappedType;
|
|
2018
|
+
newTypeVariable = this.typeReference(name, undefined) as TypeReferenceNode;
|
|
2019
|
+
templateType = instantiateType(
|
|
2020
|
+
c,
|
|
2021
|
+
getTemplateTypeFromMappedType(c, target),
|
|
2022
|
+
newTypeMapper(
|
|
2023
|
+
[getTypeParameterFromMappedType(c, target), getModifiersTypeFromMappedType(c, target)],
|
|
2024
|
+
[typeParameter, newConstraintParam],
|
|
2025
|
+
),
|
|
2026
|
+
);
|
|
2027
|
+
}
|
|
2028
|
+
let indexTarget: Node;
|
|
2029
|
+
if (newTypeVariable !== undefined) indexTarget = newTypeVariable;
|
|
2030
|
+
else indexTarget = this.typeToTypeNode(getModifiersTypeFromMappedType(c, t))!;
|
|
2031
|
+
appropriateConstraintTypeNode = this.created(new TypeOperatorNode(SyntaxKind.KeyOfKeyword, indexTarget));
|
|
2032
|
+
} else if (needsModifierPreservingWrapper) {
|
|
2033
|
+
// `{ [K in T_1]: Template }` with a new type variable as the constraint.
|
|
2034
|
+
const newParam = c.newTypeParameter(c.newSymbol(SymbolFlags.TypeParameter, 'T'));
|
|
2035
|
+
const name = this.typeParameterToName(newParam);
|
|
2036
|
+
newTypeVariable = this.typeReference(name, undefined) as TypeReferenceNode;
|
|
2037
|
+
appropriateConstraintTypeNode = newTypeVariable;
|
|
2038
|
+
} else appropriateConstraintTypeNode = this.typeToTypeNode(constraintType)!;
|
|
2039
|
+
// The name and template types are in the new scope.
|
|
2040
|
+
const exit = this.enterNewScope(declaration, undefined, [typeParameter], undefined, undefined);
|
|
2041
|
+
const typeParameterNode = this.typeParameterToDeclarationWithConstraint(
|
|
2042
|
+
typeParameter,
|
|
2043
|
+
appropriateConstraintTypeNode,
|
|
2044
|
+
);
|
|
2045
|
+
let nameTypeNode: Node | undefined = undefined;
|
|
2046
|
+
if (declaration.nameType !== undefined) nameTypeNode = this.typeToTypeNode(getNameTypeFromMappedType(c, t));
|
|
2047
|
+
const templateTypeNode = this.typeToTypeNode(
|
|
2048
|
+
removeMissingType(c, templateType, (getMappedTypeModifiers(t) & MappedTypeModifiers.IncludeOptional) !== 0),
|
|
2049
|
+
);
|
|
2050
|
+
exit();
|
|
2051
|
+
const result = this.created(
|
|
2052
|
+
new MappedTypeNode(readonlyToken, typeParameterNode, nameTypeNode, questionToken, templateTypeNode, undefined),
|
|
2053
|
+
);
|
|
2054
|
+
this.approximateLength += 10;
|
|
2055
|
+
this.context.addEmitFlags(result, EmitFlags.SingleLine);
|
|
2056
|
+
if (generateNames && this.isHomomorphicMappedTypeWithNonHomomorphicInstantiation(t)) {
|
|
2057
|
+
// `ModifiersType extends infer U ? { ...mapped type... } : never` stays homomorphic.
|
|
2058
|
+
const declaredConstraint = getEffectiveConstraint(declaration.typeParameter);
|
|
2059
|
+
let rawConstraint =
|
|
2060
|
+
declaredConstraint !== undefined && getType(declaredConstraint) !== undefined
|
|
2061
|
+
? this.getTypeFromTypeNode(getType(declaredConstraint)!, false)
|
|
2062
|
+
: undefined;
|
|
2063
|
+
if (rawConstraint !== undefined) rawConstraint = getConstraintOfTypeParameter(c, rawConstraint);
|
|
2064
|
+
const originalConstraint = instantiateType(c, rawConstraint ?? c.unknownType, t.mapper);
|
|
2065
|
+
const originalConstraintNode =
|
|
2066
|
+
(originalConstraint.flags & TypeFlags.Unknown) === 0 ? this.typeToTypeNode(originalConstraint) : undefined;
|
|
2067
|
+
return this.created(
|
|
2068
|
+
new ConditionalTypeNode(
|
|
2069
|
+
this.typeToTypeNode(getModifiersTypeFromMappedType(c, t))!,
|
|
2070
|
+
this.created(
|
|
2071
|
+
new InferTypeNode(
|
|
2072
|
+
this.created(
|
|
2073
|
+
new TypeParameterDeclaration(
|
|
2074
|
+
undefined,
|
|
2075
|
+
this.factory.cloneIdentifier(newTypeVariable!.typeName as Identifier),
|
|
2076
|
+
originalConstraintNode,
|
|
2077
|
+
undefined,
|
|
2078
|
+
undefined,
|
|
2079
|
+
),
|
|
2080
|
+
),
|
|
2081
|
+
),
|
|
2082
|
+
),
|
|
2083
|
+
result,
|
|
2084
|
+
this.keyword(SyntaxKind.NeverKeyword),
|
|
2085
|
+
),
|
|
2086
|
+
);
|
|
2087
|
+
}
|
|
2088
|
+
if (needsModifierPreservingWrapper) {
|
|
2089
|
+
// `ConstraintType extends infer T_1 extends keyof ModifiersType ? { [K in T_1]: Template } : never`.
|
|
2090
|
+
return this.created(
|
|
2091
|
+
new ConditionalTypeNode(
|
|
2092
|
+
this.typeToTypeNode(constraintType)!,
|
|
2093
|
+
this.created(
|
|
2094
|
+
new InferTypeNode(
|
|
2095
|
+
this.created(
|
|
2096
|
+
new TypeParameterDeclaration(
|
|
2097
|
+
undefined,
|
|
2098
|
+
this.factory.cloneIdentifier(newTypeVariable!.typeName as Identifier),
|
|
2099
|
+
this.created(
|
|
2100
|
+
new TypeOperatorNode(
|
|
2101
|
+
SyntaxKind.KeyOfKeyword,
|
|
2102
|
+
this.typeToTypeNode(getModifiersTypeFromMappedType(c, t))!,
|
|
2103
|
+
),
|
|
2104
|
+
),
|
|
2105
|
+
undefined,
|
|
2106
|
+
undefined,
|
|
2107
|
+
),
|
|
2108
|
+
),
|
|
2109
|
+
),
|
|
2110
|
+
),
|
|
2111
|
+
result,
|
|
2112
|
+
this.keyword(SyntaxKind.NeverKeyword),
|
|
2113
|
+
),
|
|
2114
|
+
);
|
|
2115
|
+
}
|
|
2116
|
+
return result;
|
|
2117
|
+
}
|
|
2118
|
+
|
|
2119
|
+
// ---- Type parameters
|
|
2120
|
+
|
|
2121
|
+
typeParameterToName(typeParameter: Type): Identifier {
|
|
2122
|
+
const generateNames = (this.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams) !== 0;
|
|
2123
|
+
if (generateNames) {
|
|
2124
|
+
const cached = this.typeParameterNames?.get(typeParameter.id);
|
|
2125
|
+
if (cached !== undefined) return cached;
|
|
2126
|
+
}
|
|
2127
|
+
let result = symbolToName(this, typeParameter.symbol!, SymbolFlags.Type, true);
|
|
2128
|
+
if (!(result instanceof Identifier)) return this.identifier('(Missing type parameter)');
|
|
2129
|
+
const symbol = typeParameter.symbol;
|
|
2130
|
+
if (symbol !== undefined && declarationCount(symbol) > 0) {
|
|
2131
|
+
const decl = symbol.declaration!;
|
|
2132
|
+
if (decl.kind === SyntaxKind.TypeParameter) result = this.setTextRange(result, getName(decl)) as Identifier;
|
|
2133
|
+
}
|
|
2134
|
+
if (generateNames) {
|
|
2135
|
+
const rawText = (result as Identifier).text;
|
|
2136
|
+
let i = this.typeParameterNamesByTextNextNameCount?.get(rawText) ?? 0;
|
|
2137
|
+
let text = rawText;
|
|
2138
|
+
while (
|
|
2139
|
+
this.typeParameterNamesByText?.has(text) === true ||
|
|
2140
|
+
this.typeParameterShadowsOtherTypeParameterInScope(text, typeParameter)
|
|
2141
|
+
) {
|
|
2142
|
+
i++;
|
|
2143
|
+
text = rawText + '_' + i;
|
|
2144
|
+
}
|
|
2145
|
+
if (text !== rawText) result = this.identifier(text);
|
|
2146
|
+
// Caching the largest suffix saves iterations when it grows large.
|
|
2147
|
+
const nextNameCount = this.typeParameterNamesByTextNextNameCount ?? new Map<string, number>();
|
|
2148
|
+
const names = this.typeParameterNames ?? new Map<number, Identifier>();
|
|
2149
|
+
const namesByText = this.typeParameterNamesByText ?? new Set<string>();
|
|
2150
|
+
nextNameCount.set(rawText, i);
|
|
2151
|
+
names.set(typeParameter.id, result as Identifier);
|
|
2152
|
+
namesByText.add(text);
|
|
2153
|
+
this.typeParameterNamesByTextNextNameCount = nextNameCount;
|
|
2154
|
+
this.typeParameterNames = names;
|
|
2155
|
+
this.typeParameterNamesByText = namesByText;
|
|
2156
|
+
}
|
|
2157
|
+
return result as Identifier;
|
|
2158
|
+
}
|
|
2159
|
+
|
|
2160
|
+
private typeParameterShadowsOtherTypeParameterInScope(name: string, typeParameter: Type): boolean {
|
|
2161
|
+
const result = resolveName(this.c, this.enclosingDeclaration, name, SymbolFlags.Type, undefined, false, false);
|
|
2162
|
+
return result !== undefined && (result.flags & SymbolFlags.TypeParameter) !== 0 && result !== typeParameter.symbol;
|
|
2163
|
+
}
|
|
2164
|
+
|
|
2165
|
+
typeParameterToDeclarationWithConstraint(
|
|
2166
|
+
typeParameter: Type,
|
|
2167
|
+
constraintNode: Node | undefined,
|
|
2168
|
+
): TypeParameterDeclaration {
|
|
2169
|
+
const savedFlags = this.flags;
|
|
2170
|
+
// Avoids an infinite loop on a generic in a qualified name.
|
|
2171
|
+
this.flags &= ~NodeBuilderFlags.WriteTypeParametersInQualifiedName;
|
|
2172
|
+
const modifiers = this.factory.createModifiersFromFlags(getTypeParameterModifiers(typeParameter));
|
|
2173
|
+
const name = this.typeParameterToName(typeParameter);
|
|
2174
|
+
const defaultParameter = getDefaultFromTypeParameter(this.c, typeParameter);
|
|
2175
|
+
const defaultNode = defaultParameter !== undefined ? this.typeToTypeNode(defaultParameter) : undefined;
|
|
2176
|
+
this.flags = savedFlags;
|
|
2177
|
+
return this.created(
|
|
2178
|
+
new TypeParameterDeclaration(
|
|
2179
|
+
modifiers.nodes.length > 0 ? modifiers : undefined,
|
|
2180
|
+
name,
|
|
2181
|
+
constraintNode,
|
|
2182
|
+
undefined,
|
|
2183
|
+
defaultNode,
|
|
2184
|
+
),
|
|
2185
|
+
);
|
|
2186
|
+
}
|
|
2187
|
+
|
|
2188
|
+
typeParameterToDeclaration(parameter: Type): TypeParameterDeclaration {
|
|
2189
|
+
const constraint = getConstraintOfTypeParameter(this.c, parameter);
|
|
2190
|
+
const constraintNode =
|
|
2191
|
+
constraint !== undefined
|
|
2192
|
+
? this.typeToTypeNodeWithPossibleReusableTypeNode(constraint, getConstraintDeclaration(parameter))
|
|
2193
|
+
: undefined;
|
|
2194
|
+
return this.typeParameterToDeclarationWithConstraint(parameter, constraintNode);
|
|
2195
|
+
}
|
|
2196
|
+
|
|
2197
|
+
/** The type node for `t`, reusing `typeNode` if it denotes `t`. */
|
|
2198
|
+
private typeToTypeNodeWithPossibleReusableTypeNode(
|
|
2199
|
+
t: Type | undefined,
|
|
2200
|
+
typeNode: Node | undefined,
|
|
2201
|
+
): Node | undefined {
|
|
2202
|
+
if (t === undefined) return this.keyword(SyntaxKind.AnyKeyword);
|
|
2203
|
+
if (typeNode !== undefined && this.getTypeFromTypeNode(typeNode, false) === t) {
|
|
2204
|
+
const reused = tryReuseExistingNode(this, typeNode);
|
|
2205
|
+
if (reused !== undefined) return reused;
|
|
2206
|
+
}
|
|
2207
|
+
return this.typeToTypeNode(t);
|
|
2208
|
+
}
|
|
2209
|
+
|
|
2210
|
+
typeParametersToTypeParameterDeclarations(symbol: Symbol): Node[] {
|
|
2211
|
+
const c = this.c;
|
|
2212
|
+
const targetSymbol = getTargetSymbol(c, symbol);
|
|
2213
|
+
const results: Node[] = [];
|
|
2214
|
+
if ((targetSymbol.flags & (SymbolFlags.Class | SymbolFlags.Interface | SymbolFlags.Alias)) !== 0) {
|
|
2215
|
+
for (const param of getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(c, symbol))
|
|
2216
|
+
results.push(this.typeParameterToDeclaration(param));
|
|
2217
|
+
} else if ((targetSymbol.flags & SymbolFlags.Function) !== 0 && symbol.valueDeclaration !== undefined) {
|
|
2218
|
+
for (const param of getTypeParametersFromDeclaration(c, symbol.valueDeclaration))
|
|
2219
|
+
results.push(this.typeParameterToDeclaration(param));
|
|
2220
|
+
}
|
|
2221
|
+
return results;
|
|
2222
|
+
}
|
|
2223
|
+
|
|
2224
|
+
getTypeParametersOfClassOrInterface(symbol: Symbol): Type[] {
|
|
2225
|
+
const declared = getDeclaredTypeOfClassOrInterface(this.c, symbol);
|
|
2226
|
+
return declared.outerTypeParameters().concat(declared.localTypeParameters());
|
|
2227
|
+
}
|
|
2228
|
+
|
|
2229
|
+
// ---- Signatures
|
|
2230
|
+
|
|
2231
|
+
signatureToSignatureDeclaration(
|
|
2232
|
+
signature: Signature,
|
|
2233
|
+
kind: SyntaxKind,
|
|
2234
|
+
options: SignatureDeclarationOptions | undefined,
|
|
2235
|
+
): Node {
|
|
2236
|
+
const c = this.c;
|
|
2237
|
+
const exit = this.enterSignatureScope(signature);
|
|
2238
|
+
const expandedParams = this.expandedParameters;
|
|
2239
|
+
// Usually more, but 3 is the minimum.
|
|
2240
|
+
this.approximateLength += 3;
|
|
2241
|
+
const typeParameters: Node[] = [];
|
|
2242
|
+
if (
|
|
2243
|
+
(this.flags & NodeBuilderFlags.WriteTypeArgumentsOfSignature) !== 0 &&
|
|
2244
|
+
signature.target !== undefined &&
|
|
2245
|
+
signature.mapper !== undefined &&
|
|
2246
|
+
signature.target.typeParameters.length !== 0
|
|
2247
|
+
) {
|
|
2248
|
+
for (const parameter of signature.target.typeParameters) {
|
|
2249
|
+
const node = this.typeToTypeNode(instantiateType(c, parameter, signature.mapper));
|
|
2250
|
+
if (node !== undefined) typeParameters.push(node);
|
|
2251
|
+
}
|
|
2252
|
+
} else
|
|
2253
|
+
for (const parameter of signature.typeParameters) typeParameters.push(this.typeParameterToDeclaration(parameter));
|
|
2254
|
+
const savedFlags = this.flags;
|
|
2255
|
+
this.flags &= ~NodeBuilderFlags.SuppressAnyReturnType;
|
|
2256
|
+
// An expanded parameter list with a variadic before its end isn't used.
|
|
2257
|
+
let useOriginal = false;
|
|
2258
|
+
for (const p of expandedParams)
|
|
2259
|
+
if (p !== expandedParams[expandedParams.length - 1] && (p.checkFlags & CheckFlags.RestParameter) !== 0)
|
|
2260
|
+
useOriginal = true;
|
|
2261
|
+
const parameters: Node[] = [];
|
|
2262
|
+
const thisParameter =
|
|
2263
|
+
(this.flags & NodeBuilderFlags.OmitThisParameter) !== 0
|
|
2264
|
+
? undefined
|
|
2265
|
+
: this.tryGetThisParameterDeclaration(signature);
|
|
2266
|
+
if (thisParameter !== undefined) parameters.push(thisParameter);
|
|
2267
|
+
for (const parameter of useOriginal ? signature.parameters : expandedParams)
|
|
2268
|
+
parameters.push(this.symbolToParameterDeclaration(parameter, kind === SyntaxKind.Constructor));
|
|
2269
|
+
this.flags = savedFlags;
|
|
2270
|
+
let returnTypeNode = this.serializeReturnTypeForSignature(signature);
|
|
2271
|
+
let modifiers = options !== undefined ? options.modifiers : [];
|
|
2272
|
+
if (kind === SyntaxKind.ConstructorType && (signature.flags & SignatureFlags.Abstract) !== 0) {
|
|
2273
|
+
let flags = ModifierFlags.Abstract;
|
|
2274
|
+
for (const m of modifiers) flags |= modifierToFlag(m.kind);
|
|
2275
|
+
modifiers = this.factory.createModifiersFromFlags(flags).nodes;
|
|
2276
|
+
}
|
|
2277
|
+
const paramList = this.list(parameters);
|
|
2278
|
+
const typeParamList = typeParameters.length !== 0 ? this.list(typeParameters) : undefined;
|
|
2279
|
+
const modifierList = this.modifierList(modifiers);
|
|
2280
|
+
const name = (options !== undefined ? options.name : undefined) ?? this.identifier('');
|
|
2281
|
+
let node: Node;
|
|
2282
|
+
switch (kind) {
|
|
2283
|
+
case SyntaxKind.CallSignature:
|
|
2284
|
+
node = this.created(new CallSignatureDeclaration(typeParamList, paramList, returnTypeNode));
|
|
2285
|
+
break;
|
|
2286
|
+
case SyntaxKind.ConstructSignature:
|
|
2287
|
+
node = this.created(new ConstructSignatureDeclaration(typeParamList, paramList, returnTypeNode));
|
|
2288
|
+
break;
|
|
2289
|
+
case SyntaxKind.MethodSignature:
|
|
2290
|
+
node = this.created(
|
|
2291
|
+
new MethodSignatureDeclaration(
|
|
2292
|
+
modifierList,
|
|
2293
|
+
name,
|
|
2294
|
+
options !== undefined ? options.questionToken : undefined,
|
|
2295
|
+
typeParamList,
|
|
2296
|
+
paramList,
|
|
2297
|
+
returnTypeNode,
|
|
2298
|
+
),
|
|
2299
|
+
);
|
|
2300
|
+
break;
|
|
2301
|
+
case SyntaxKind.MethodDeclaration:
|
|
2302
|
+
node = this.created(
|
|
2303
|
+
new MethodDeclaration(
|
|
2304
|
+
modifierList,
|
|
2305
|
+
undefined,
|
|
2306
|
+
name,
|
|
2307
|
+
undefined,
|
|
2308
|
+
typeParamList,
|
|
2309
|
+
paramList,
|
|
2310
|
+
returnTypeNode,
|
|
2311
|
+
undefined,
|
|
2312
|
+
undefined,
|
|
2313
|
+
),
|
|
2314
|
+
);
|
|
2315
|
+
break;
|
|
2316
|
+
case SyntaxKind.Constructor:
|
|
2317
|
+
node = this.created(
|
|
2318
|
+
new ConstructorDeclaration(modifierList, undefined, paramList, undefined, undefined, undefined),
|
|
2319
|
+
);
|
|
2320
|
+
break;
|
|
2321
|
+
case SyntaxKind.GetAccessor:
|
|
2322
|
+
node = this.created(
|
|
2323
|
+
new GetAccessorDeclaration(modifierList, name, undefined, paramList, returnTypeNode, undefined, undefined),
|
|
2324
|
+
);
|
|
2325
|
+
break;
|
|
2326
|
+
case SyntaxKind.SetAccessor:
|
|
2327
|
+
node = this.created(
|
|
2328
|
+
new SetAccessorDeclaration(modifierList, name, undefined, paramList, undefined, undefined, undefined),
|
|
2329
|
+
);
|
|
2330
|
+
break;
|
|
2331
|
+
case SyntaxKind.IndexSignature:
|
|
2332
|
+
node = this.created(new IndexSignatureDeclaration(modifierList, paramList, returnTypeNode));
|
|
2333
|
+
break;
|
|
2334
|
+
case SyntaxKind.FunctionType:
|
|
2335
|
+
if (returnTypeNode === undefined) returnTypeNode = this.typeReference(this.identifier(''), undefined);
|
|
2336
|
+
node = this.created(new FunctionTypeNode(typeParamList, paramList, returnTypeNode));
|
|
2337
|
+
break;
|
|
2338
|
+
case SyntaxKind.ConstructorType:
|
|
2339
|
+
if (returnTypeNode === undefined) returnTypeNode = this.typeReference(this.identifier(''), undefined);
|
|
2340
|
+
node = this.created(new ConstructorTypeNode(modifierList, typeParamList, paramList, returnTypeNode));
|
|
2341
|
+
break;
|
|
2342
|
+
case SyntaxKind.FunctionDeclaration:
|
|
2343
|
+
node = this.created(
|
|
2344
|
+
new FunctionDeclaration(
|
|
2345
|
+
modifierList,
|
|
2346
|
+
undefined,
|
|
2347
|
+
name as Identifier,
|
|
2348
|
+
typeParamList,
|
|
2349
|
+
paramList,
|
|
2350
|
+
returnTypeNode,
|
|
2351
|
+
undefined,
|
|
2352
|
+
undefined,
|
|
2353
|
+
),
|
|
2354
|
+
);
|
|
2355
|
+
break;
|
|
2356
|
+
case SyntaxKind.FunctionExpression:
|
|
2357
|
+
node = this.created(
|
|
2358
|
+
new FunctionExpression(
|
|
2359
|
+
modifierList,
|
|
2360
|
+
undefined,
|
|
2361
|
+
name as Identifier,
|
|
2362
|
+
typeParamList,
|
|
2363
|
+
paramList,
|
|
2364
|
+
returnTypeNode,
|
|
2365
|
+
undefined,
|
|
2366
|
+
this.created(new Block(this.list([]), false)),
|
|
2367
|
+
),
|
|
2368
|
+
);
|
|
2369
|
+
break;
|
|
2370
|
+
case SyntaxKind.ArrowFunction:
|
|
2371
|
+
node = this.created(
|
|
2372
|
+
new ArrowFunction(
|
|
2373
|
+
modifierList,
|
|
2374
|
+
typeParamList,
|
|
2375
|
+
paramList,
|
|
2376
|
+
returnTypeNode,
|
|
2377
|
+
undefined,
|
|
2378
|
+
undefined,
|
|
2379
|
+
this.created(new Block(this.list([]), false)),
|
|
2380
|
+
),
|
|
2381
|
+
);
|
|
2382
|
+
break;
|
|
2383
|
+
default:
|
|
2384
|
+
throw new Error('Unhandled kind in signatureToSignatureDeclaration');
|
|
2385
|
+
}
|
|
2386
|
+
exit();
|
|
2387
|
+
return node;
|
|
2388
|
+
}
|
|
2389
|
+
|
|
2390
|
+
private tryGetThisParameterDeclaration(signature: Signature): Node | undefined {
|
|
2391
|
+
if (signature.thisParameter !== undefined) return this.symbolToParameterDeclaration(signature.thisParameter, false);
|
|
2392
|
+
return undefined;
|
|
2393
|
+
}
|
|
2394
|
+
|
|
2395
|
+
symbolToParameterDeclaration(parameterSymbol: Symbol, preserveModifierFlags: boolean): Node {
|
|
2396
|
+
const c = this.c;
|
|
2397
|
+
const parameterDeclaration = getEffectiveParameterDeclaration(parameterSymbol);
|
|
2398
|
+
const parameterType = getTypeOfSymbol(c, parameterSymbol);
|
|
2399
|
+
const parameterTypeNode = this.serializeTypeForDeclaration(
|
|
2400
|
+
parameterDeclaration,
|
|
2401
|
+
parameterType,
|
|
2402
|
+
parameterSymbol,
|
|
2403
|
+
true,
|
|
2404
|
+
);
|
|
2405
|
+
let modifiers: ModifierList | undefined = undefined;
|
|
2406
|
+
if (
|
|
2407
|
+
(this.flags & NodeBuilderFlags.OmitParameterModifiers) === 0 &&
|
|
2408
|
+
preserveModifierFlags &&
|
|
2409
|
+
parameterDeclaration !== undefined
|
|
2410
|
+
) {
|
|
2411
|
+
const original = getModifiers(parameterDeclaration);
|
|
2412
|
+
if (original !== undefined) {
|
|
2413
|
+
// Copies keep the source positions and flags, as tsgo does; its positions are UTF-8 offsets.
|
|
2414
|
+
const text = getSourceFileOfNode(parameterDeclaration).text;
|
|
2415
|
+
const clones: Node[] = [];
|
|
2416
|
+
for (const m of original.nodes) {
|
|
2417
|
+
if (!isModifierKind(m.kind)) continue;
|
|
2418
|
+
const clone = m.deepClone();
|
|
2419
|
+
clone.pos = utf8Offset(text, m.pos) | 0;
|
|
2420
|
+
clone.end = utf8Offset(text, m.end) | 0;
|
|
2421
|
+
clones.push(clone);
|
|
2422
|
+
}
|
|
2423
|
+
modifiers = this.modifierList(clones);
|
|
2424
|
+
}
|
|
2425
|
+
}
|
|
2426
|
+
const isRest =
|
|
2427
|
+
(parameterDeclaration instanceof ParameterDeclaration && parameterDeclaration.dotDotDotToken !== undefined) ||
|
|
2428
|
+
(parameterSymbol.checkFlags & CheckFlags.RestParameter) !== 0;
|
|
2429
|
+
const name = this.parameterToParameterDeclarationName(parameterSymbol, parameterDeclaration);
|
|
2430
|
+
const isOptional =
|
|
2431
|
+
(parameterDeclaration !== undefined && isOptionalParameter(c, parameterDeclaration)) ||
|
|
2432
|
+
(parameterSymbol.checkFlags & CheckFlags.OptionalParameter) !== 0;
|
|
2433
|
+
const parameterNode = this.created(
|
|
2434
|
+
new ParameterDeclaration(
|
|
2435
|
+
modifiers,
|
|
2436
|
+
isRest ? this.token(SyntaxKind.DotDotDotToken) : undefined,
|
|
2437
|
+
name,
|
|
2438
|
+
isOptional ? this.token(SyntaxKind.QuestionToken) : undefined,
|
|
2439
|
+
parameterTypeNode,
|
|
2440
|
+
undefined,
|
|
2441
|
+
),
|
|
2442
|
+
);
|
|
2443
|
+
this.approximateLength += parameterSymbol.name.length + 3;
|
|
2444
|
+
return parameterNode;
|
|
2445
|
+
}
|
|
2446
|
+
|
|
2447
|
+
parameterToParameterDeclarationName(parameterSymbol: Symbol, parameterDeclaration: Node | undefined): Node {
|
|
2448
|
+
const name = parameterDeclaration === undefined ? undefined : getName(parameterDeclaration);
|
|
2449
|
+
if (name === undefined) return this.identifier(parameterSymbol.name);
|
|
2450
|
+
switch (name.kind) {
|
|
2451
|
+
case SyntaxKind.Identifier: {
|
|
2452
|
+
const cloned = this.cloneSynthesized(name);
|
|
2453
|
+
this.context.setEmitFlags(cloned, EmitFlags.NoAsciiEscaping);
|
|
2454
|
+
return cloned;
|
|
2455
|
+
}
|
|
2456
|
+
case SyntaxKind.QualifiedName: {
|
|
2457
|
+
const cloned = this.cloneSynthesized((name as QualifiedName).right);
|
|
2458
|
+
this.context.setEmitFlags(cloned, EmitFlags.NoAsciiEscaping);
|
|
2459
|
+
return cloned;
|
|
2460
|
+
}
|
|
2461
|
+
}
|
|
2462
|
+
return cloneBindingName(this, name);
|
|
2463
|
+
}
|
|
2464
|
+
|
|
2465
|
+
/**
|
|
2466
|
+
* A copy of `node`'s subtree without positions, as tsgo's `DeepCloneNode`: each copy has its
|
|
2467
|
+
* node as original, and so its emit flags.
|
|
2468
|
+
*/
|
|
2469
|
+
deepCloneNode(node: Node): Node {
|
|
2470
|
+
const clone = node.deepClone();
|
|
2471
|
+
clearPositions(clone);
|
|
2472
|
+
linkClones(this.context, clone, node);
|
|
2473
|
+
return clone;
|
|
2474
|
+
}
|
|
2475
|
+
|
|
2476
|
+
/** A copy of `node` without positions. */
|
|
2477
|
+
cloneSynthesized(node: Node): Node {
|
|
2478
|
+
const clone = node.deepClone();
|
|
2479
|
+
clearPositions(clone);
|
|
2480
|
+
return clone;
|
|
2481
|
+
}
|
|
2482
|
+
|
|
2483
|
+
/**
|
|
2484
|
+
* The type node for `t` declared by `declaration` (or `symbol`'s declaration). A symbol's own
|
|
2485
|
+
* `unique symbol` type is written as such rather than `typeof symbol`.
|
|
2486
|
+
*/
|
|
2487
|
+
serializeTypeForDeclaration(
|
|
2488
|
+
declaration: Node | undefined,
|
|
2489
|
+
type: Type | undefined,
|
|
2490
|
+
symbol: Symbol | undefined,
|
|
2491
|
+
tryReuse: boolean,
|
|
2492
|
+
): Node {
|
|
2493
|
+
const c = this.c;
|
|
2494
|
+
if (declaration === undefined && symbol !== undefined)
|
|
2495
|
+
declaration = symbol.valueDeclaration ?? (declarationCount(symbol) > 0 ? symbol.declaration! : undefined);
|
|
2496
|
+
if (symbol === undefined && declaration !== undefined) symbol = getSymbolOfDeclaration(c, declaration);
|
|
2497
|
+
let t = type;
|
|
2498
|
+
if (t === undefined && symbol !== undefined) {
|
|
2499
|
+
t = this.enclosingSymbolTypes.get(getSymbolId(symbol));
|
|
2500
|
+
if (t === undefined) {
|
|
2501
|
+
if (
|
|
2502
|
+
(symbol.flags & SymbolFlags.Accessor) !== 0 &&
|
|
2503
|
+
declaration !== undefined &&
|
|
2504
|
+
declaration.kind === SyntaxKind.SetAccessor
|
|
2505
|
+
)
|
|
2506
|
+
t = instantiateType(c, getWriteTypeOfSymbol(c, symbol), this.mapper);
|
|
2507
|
+
else if ((symbol.flags & (SymbolFlags.TypeLiteral | SymbolFlags.Signature)) === 0)
|
|
2508
|
+
t = instantiateType(c, getWidenedLiteralType(c, getTypeOfSymbol(c, symbol)), this.mapper);
|
|
2509
|
+
else t = c.errorType;
|
|
2510
|
+
}
|
|
2511
|
+
}
|
|
2512
|
+
if (t === undefined) t = c.errorType;
|
|
2513
|
+
if (this.pseudo !== undefined) return this.serializeTypeForDeclarationReusing(declaration, t, symbol, tryReuse);
|
|
2514
|
+
if (
|
|
2515
|
+
declaration !== undefined &&
|
|
2516
|
+
declaration.kind === SyntaxKind.Parameter &&
|
|
2517
|
+
requiresAddingImplicitUndefined(c, declaration, this.enclosingDeclaration)
|
|
2518
|
+
)
|
|
2519
|
+
t = getOptionalType(c, t, false);
|
|
2520
|
+
const savedFlags = this.flags;
|
|
2521
|
+
if (
|
|
2522
|
+
(t.flags & TypeFlags.UniqueESSymbol) !== 0 &&
|
|
2523
|
+
symbol !== undefined &&
|
|
2524
|
+
t.symbol === symbol &&
|
|
2525
|
+
(this.enclosingDeclaration === undefined || this.isDeclaredInEnclosingFile(symbol))
|
|
2526
|
+
)
|
|
2527
|
+
this.flags |= NodeBuilderFlags.AllowUniqueESSymbolType;
|
|
2528
|
+
const result = this.typeToTypeNode(t);
|
|
2529
|
+
this.flags = savedFlags;
|
|
2530
|
+
return result ?? this.keyword(SyntaxKind.AnyKeyword);
|
|
2531
|
+
}
|
|
2532
|
+
|
|
2533
|
+
/** `serializeTypeForDeclaration` with declaration emit's reuse of what the source wrote. */
|
|
2534
|
+
private serializeTypeForDeclarationReusing(
|
|
2535
|
+
declaration: Node | undefined,
|
|
2536
|
+
typeIn: Type,
|
|
2537
|
+
symbol: Symbol | undefined,
|
|
2538
|
+
tryReuse: boolean,
|
|
2539
|
+
): Node {
|
|
2540
|
+
const c = this.c;
|
|
2541
|
+
const pseudo = this.pseudo!;
|
|
2542
|
+
let t = typeIn;
|
|
2543
|
+
const isPropertyLike =
|
|
2544
|
+
declaration !== undefined &&
|
|
2545
|
+
(declaration.kind === SyntaxKind.Parameter ||
|
|
2546
|
+
declaration.kind === SyntaxKind.PropertySignature ||
|
|
2547
|
+
declaration.kind === SyntaxKind.PropertyDeclaration);
|
|
2548
|
+
const requiresAddingUndefined =
|
|
2549
|
+
isPropertyLike &&
|
|
2550
|
+
requiresAddingImplicitUndefinedForDeclaration(c, declaration!, symbol, this.enclosingDeclaration);
|
|
2551
|
+
if (requiresAddingUndefined && declaration!.kind === SyntaxKind.Parameter) t = getOptionalType(c, t, false);
|
|
2552
|
+
const savedFlags = this.flags;
|
|
2553
|
+
if (
|
|
2554
|
+
(t.flags & TypeFlags.UniqueESSymbol) !== 0 &&
|
|
2555
|
+
symbol !== undefined &&
|
|
2556
|
+
t.symbol === symbol &&
|
|
2557
|
+
(this.enclosingDeclaration === undefined || this.isDeclaredInEnclosingFile(symbol))
|
|
2558
|
+
)
|
|
2559
|
+
this.flags |= NodeBuilderFlags.AllowUniqueESSymbolType;
|
|
2560
|
+
let result: Node | undefined = undefined;
|
|
2561
|
+
let reportedInferenceFallback = false;
|
|
2562
|
+
if (
|
|
2563
|
+
tryReuse &&
|
|
2564
|
+
this.enclosingDeclaration !== undefined &&
|
|
2565
|
+
declaration !== undefined &&
|
|
2566
|
+
symbol !== undefined &&
|
|
2567
|
+
(isAccessorKind(declaration) ||
|
|
2568
|
+
(hasInferredTypeKind(declaration) &&
|
|
2569
|
+
(declaration.flags & NodeFlags.Synthesized) === 0 &&
|
|
2570
|
+
(t.objectFlags & ObjectFlags.RequiresWidening) === 0))
|
|
2571
|
+
) {
|
|
2572
|
+
const remove = this.addSymbolTypeToContext(symbol, t);
|
|
2573
|
+
let pt: PseudoType = isAccessorKind(declaration)
|
|
2574
|
+
? pseudo.getTypeOfAccessor(declaration)
|
|
2575
|
+
: pseudo.getTypeOfDeclaration(declaration);
|
|
2576
|
+
if (pt.kind === PseudoTypeKind.NoResult && declaration.kind === SyntaxKind.BinaryExpression) {
|
|
2577
|
+
// The first annotated assignment declares the type for the rest.
|
|
2578
|
+
for (const d of getDeclarations(symbol))
|
|
2579
|
+
if (getType(d) !== undefined) {
|
|
2580
|
+
pt = pseudo.getTypeOfDeclaration(d);
|
|
2581
|
+
break;
|
|
2582
|
+
}
|
|
2583
|
+
}
|
|
2584
|
+
const reportErrors = !this.suppressReportInferenceFallback;
|
|
2585
|
+
if (
|
|
2586
|
+
pseudoTypeEquivalentToType(
|
|
2587
|
+
this,
|
|
2588
|
+
pt,
|
|
2589
|
+
t,
|
|
2590
|
+
!requiresAddingUndefined && isPropertyLike && hasQuestionToken(declaration),
|
|
2591
|
+
reportErrors,
|
|
2592
|
+
)
|
|
2593
|
+
) {
|
|
2594
|
+
const ptt = pseudoTypeToType(this, pt);
|
|
2595
|
+
if (
|
|
2596
|
+
ptt !== undefined &&
|
|
2597
|
+
requiresAddingUndefined &&
|
|
2598
|
+
containsNonMissingUndefinedType(c, t) &&
|
|
2599
|
+
!containsNonMissingUndefinedType(c, ptt)
|
|
2600
|
+
)
|
|
2601
|
+
pt = new PseudoUnionType([pt, pseudoUndefinedType]);
|
|
2602
|
+
result = pseudoTypeToNodeWithCheckerFallback(this, pt, t);
|
|
2603
|
+
} else {
|
|
2604
|
+
// Errors reported inside an inferred pseudo-type aren't reported again by the fallback.
|
|
2605
|
+
reportedInferenceFallback = reportErrors && pt instanceof InferredType && pt.errorNodes.length > 0;
|
|
2606
|
+
let shouldAddUndefined = false;
|
|
2607
|
+
if (requiresAddingUndefined) {
|
|
2608
|
+
const ptt = pseudoTypeToType(this, pt);
|
|
2609
|
+
shouldAddUndefined =
|
|
2610
|
+
ptt !== undefined ? !containsNonMissingUndefinedType(c, ptt) : !couldAlreadyReferToUndefined(pt);
|
|
2611
|
+
}
|
|
2612
|
+
if (shouldAddUndefined) {
|
|
2613
|
+
pt = new PseudoUnionType([pt, pseudoUndefinedType]);
|
|
2614
|
+
if (pseudoTypeEquivalentToType(this, pt, t, false, reportErrors)) {
|
|
2615
|
+
result = pseudoTypeToNodeWithCheckerFallback(this, pt, t);
|
|
2616
|
+
reportedInferenceFallback = false;
|
|
2617
|
+
}
|
|
2618
|
+
}
|
|
2619
|
+
}
|
|
2620
|
+
remove();
|
|
2621
|
+
}
|
|
2622
|
+
if (result === undefined) {
|
|
2623
|
+
if (reportedInferenceFallback) {
|
|
2624
|
+
const oldSuppress = this.suppressReportInferenceFallback;
|
|
2625
|
+
this.suppressReportInferenceFallback = true;
|
|
2626
|
+
result = this.typeToTypeNode(t);
|
|
2627
|
+
this.suppressReportInferenceFallback = oldSuppress;
|
|
2628
|
+
} else result = this.typeToTypeNode(t);
|
|
2629
|
+
}
|
|
2630
|
+
this.flags = savedFlags;
|
|
2631
|
+
return result ?? this.keyword(SyntaxKind.AnyKeyword);
|
|
2632
|
+
}
|
|
2633
|
+
|
|
2634
|
+
/** The return type node of `signature`; `any` is omitted with `SuppressAnyReturnType`. */
|
|
2635
|
+
serializeReturnTypeForSignature(signature: Signature): Node | undefined {
|
|
2636
|
+
return this.serializeReturnTypeForSignatureEx(signature, true);
|
|
2637
|
+
}
|
|
2638
|
+
|
|
2639
|
+
/** `serializeReturnTypeForSignature`; with `tryReuse` and a pseudochecker, the source's return type where it matches. */
|
|
2640
|
+
serializeReturnTypeForSignatureEx(signature: Signature, tryReuse: boolean): Node | undefined {
|
|
2641
|
+
const c = this.c;
|
|
2642
|
+
const suppressAny = (this.flags & NodeBuilderFlags.SuppressAnyReturnType) !== 0;
|
|
2643
|
+
const savedFlags = this.flags;
|
|
2644
|
+
// Only top-level `any`s are suppressed.
|
|
2645
|
+
if (suppressAny) this.flags &= ~NodeBuilderFlags.SuppressAnyReturnType;
|
|
2646
|
+
let returnType: Type;
|
|
2647
|
+
const declaration = signature.declaration;
|
|
2648
|
+
if (declaration !== undefined && (declaration.flags & NodeFlags.Synthesized) === 0) {
|
|
2649
|
+
const symbol = getSymbolOfDeclaration(c, declaration);
|
|
2650
|
+
const known = symbol !== undefined ? this.enclosingSymbolTypes.get(getSymbolId(symbol)) : undefined;
|
|
2651
|
+
returnType = known ?? instantiateType(c, getReturnTypeOfSignature(c, signature), this.mapper);
|
|
2652
|
+
} else returnType = getReturnTypeOfSignature(c, signature);
|
|
2653
|
+
let returnTypeNode: Node | undefined = undefined;
|
|
2654
|
+
if (!(suppressAny && (returnType.flags & TypeFlags.Any) !== 0)) {
|
|
2655
|
+
if (
|
|
2656
|
+
this.pseudo !== undefined &&
|
|
2657
|
+
tryReuse &&
|
|
2658
|
+
this.enclosingDeclaration !== undefined &&
|
|
2659
|
+
declaration !== undefined &&
|
|
2660
|
+
(declaration.flags & NodeFlags.Synthesized) === 0
|
|
2661
|
+
)
|
|
2662
|
+
returnTypeNode = this.serializeReturnTypeReusing(signature, declaration, returnType);
|
|
2663
|
+
if (returnTypeNode === undefined)
|
|
2664
|
+
returnTypeNode = this.serializeInferredReturnTypeForSignature(signature, returnType);
|
|
2665
|
+
}
|
|
2666
|
+
if (returnTypeNode === undefined && !suppressAny) returnTypeNode = this.keyword(SyntaxKind.AnyKeyword);
|
|
2667
|
+
this.flags = savedFlags;
|
|
2668
|
+
return returnTypeNode;
|
|
2669
|
+
}
|
|
2670
|
+
|
|
2671
|
+
private serializeReturnTypeReusing(signature: Signature, declaration: Node, returnType: Type): Node | undefined {
|
|
2672
|
+
const declarationSymbol = getSymbolOfDeclaration(this.c, declaration);
|
|
2673
|
+
if (declarationSymbol === undefined) return undefined;
|
|
2674
|
+
const restore = this.addSymbolTypeToContext(declarationSymbol, returnType);
|
|
2675
|
+
let result: Node | undefined = undefined;
|
|
2676
|
+
let pt: PseudoType | undefined = this.pseudo!.getReturnTypeOfSignature(declaration);
|
|
2677
|
+
if (pseudoTypeEquivalentToType(this, pt, returnType, false, !this.suppressReportInferenceFallback)) {
|
|
2678
|
+
// The pseudochecker doesn't infer type predicates, which the checker may have.
|
|
2679
|
+
const typePredicate = getTypePredicateOfSignature(this.c, signature);
|
|
2680
|
+
if (typePredicate !== undefined && !pseudoReturnTypeMatchesPredicate(this, pt, typePredicate)) {
|
|
2681
|
+
if (!this.suppressReportInferenceFallback) this.tracker.reportInferenceFallback(declaration);
|
|
2682
|
+
pt = undefined;
|
|
2683
|
+
}
|
|
2684
|
+
if (pt !== undefined) result = pseudoTypeToNodeWithCheckerFallback(this, pt, returnType);
|
|
2685
|
+
}
|
|
2686
|
+
restore();
|
|
2687
|
+
return result;
|
|
2688
|
+
}
|
|
2689
|
+
|
|
2690
|
+
private serializeInferredReturnTypeForSignature(signature: Signature, returnType: Type): Node | undefined {
|
|
2691
|
+
const oldSuppress = this.suppressReportInferenceFallback;
|
|
2692
|
+
this.suppressReportInferenceFallback = true;
|
|
2693
|
+
const typePredicate = getTypePredicateOfSignature(this.c, signature);
|
|
2694
|
+
let returnTypeNode: Node | undefined;
|
|
2695
|
+
if (typePredicate !== undefined) {
|
|
2696
|
+
const predicate =
|
|
2697
|
+
this.mapper !== undefined ? instantiateTypePredicate(this.c, typePredicate, this.mapper) : typePredicate;
|
|
2698
|
+
returnTypeNode = this.typePredicateToTypePredicateNode(predicate);
|
|
2699
|
+
} else returnTypeNode = this.typeToTypeNode(returnType);
|
|
2700
|
+
this.suppressReportInferenceFallback = oldSuppress;
|
|
2701
|
+
return returnTypeNode;
|
|
2702
|
+
}
|
|
2703
|
+
|
|
2704
|
+
typePredicateToTypePredicateNode(predicate: TypePredicate): Node {
|
|
2705
|
+
const isAsserts =
|
|
2706
|
+
predicate.kind === TypePredicateKind.AssertsThis || predicate.kind === TypePredicateKind.AssertsIdentifier;
|
|
2707
|
+
let parameterName: Node;
|
|
2708
|
+
if (predicate.kind === TypePredicateKind.Identifier || predicate.kind === TypePredicateKind.AssertsIdentifier) {
|
|
2709
|
+
parameterName = this.identifier(predicate.parameterName);
|
|
2710
|
+
this.context.setEmitFlags(parameterName, EmitFlags.NoAsciiEscaping);
|
|
2711
|
+
} else parameterName = this.created(new ThisTypeNode());
|
|
2712
|
+
const typeNode = predicate.type !== undefined ? this.typeToTypeNode(predicate.type) : undefined;
|
|
2713
|
+
return this.created(
|
|
2714
|
+
new TypePredicateNode(isAsserts ? this.token(SyntaxKind.AssertsKeyword) : undefined, parameterName, typeNode),
|
|
2715
|
+
);
|
|
2716
|
+
}
|
|
2717
|
+
|
|
2718
|
+
// ---- Existing type nodes
|
|
2719
|
+
|
|
2720
|
+
/** The type of a type node, instantiated with the scope's mapper; with `noMappedTypes`, undefined if that changes it. */
|
|
2721
|
+
getTypeFromTypeNode(node: Node, noMappedTypes: boolean): Type | undefined {
|
|
2722
|
+
const t = getTypeFromTypeNode(this.c, node);
|
|
2723
|
+
if (this.mapper === undefined) return t;
|
|
2724
|
+
const instantiated = instantiateType(this.c, t, this.mapper);
|
|
2725
|
+
if (noMappedTypes && instantiated !== t) return undefined;
|
|
2726
|
+
return instantiated;
|
|
2727
|
+
}
|
|
2728
|
+
|
|
2729
|
+
private typeNodeIsEquivalentToType(annotatedDeclaration: Node | undefined, t: Type, typeFromTypeNode: Type): boolean {
|
|
2730
|
+
if (typeFromTypeNode === t) return true;
|
|
2731
|
+
if (annotatedDeclaration === undefined) return false;
|
|
2732
|
+
if (getQuestionToken(annotatedDeclaration) !== undefined)
|
|
2733
|
+
return getTypeWithFacts(this.c, t, TypeFacts.NEUndefined) === typeFromTypeNode;
|
|
2734
|
+
return false;
|
|
2735
|
+
}
|
|
2736
|
+
|
|
2737
|
+
tryReuseExistingNonParameterTypeNode(
|
|
2738
|
+
existing: Node,
|
|
2739
|
+
t: Type,
|
|
2740
|
+
host: Node | undefined,
|
|
2741
|
+
annotationType: Type | undefined,
|
|
2742
|
+
): Node | undefined {
|
|
2743
|
+
const annotation = annotationType ?? this.getTypeFromTypeNode(existing, true);
|
|
2744
|
+
if (
|
|
2745
|
+
annotation !== undefined &&
|
|
2746
|
+
this.typeNodeIsEquivalentToType(host ?? this.enclosingDeclaration, t, annotation) &&
|
|
2747
|
+
canReuseExistingJSTypeNode(this, existing, t)
|
|
2748
|
+
)
|
|
2749
|
+
return tryReuseExistingNode(this, existing);
|
|
2750
|
+
return undefined;
|
|
2751
|
+
}
|
|
2752
|
+
|
|
2753
|
+
/**
|
|
2754
|
+
* A copy of `range` positioned like `location`: without positions unless both are in the file
|
|
2755
|
+
* being written, with `location` as its original.
|
|
2756
|
+
*/
|
|
2757
|
+
setTextRange(range: Node, location: Node | undefined): Node {
|
|
2758
|
+
// Always a copy, so positions from other files never leak into the result. As tsgo's
|
|
2759
|
+
// shallow clone, the copy and its descendants keep their emit flags.
|
|
2760
|
+
const result = range.deepClone();
|
|
2761
|
+
copyEmitNodes(this.context, result, range, true);
|
|
2762
|
+
result.pos = -1;
|
|
2763
|
+
result.end = -1;
|
|
2764
|
+
this.context.setOriginal(result, range);
|
|
2765
|
+
if (location === undefined || result === location) return result;
|
|
2766
|
+
let original = this.context.getOriginal(result);
|
|
2767
|
+
while (original !== undefined && original !== location) original = this.context.getOriginal(original);
|
|
2768
|
+
if (original === undefined) this.context.setOriginalEx(result, location, true);
|
|
2769
|
+
if (
|
|
2770
|
+
this.enclosingFile !== undefined &&
|
|
2771
|
+
this.enclosingFile === getSourceFileOfNode(this.context.mostOriginal(location))
|
|
2772
|
+
) {
|
|
2773
|
+
result.pos = location.pos;
|
|
2774
|
+
result.end = location.end;
|
|
2775
|
+
} else {
|
|
2776
|
+
result.pos = -1;
|
|
2777
|
+
result.end = -1;
|
|
2778
|
+
}
|
|
2779
|
+
return result;
|
|
2780
|
+
}
|
|
2781
|
+
}
|
|
2782
|
+
|
|
2783
|
+
const enum TransformKind {
|
|
2784
|
+
Type,
|
|
2785
|
+
TypeReference,
|
|
2786
|
+
Conditional,
|
|
2787
|
+
ObjectType,
|
|
2788
|
+
}
|
|
2789
|
+
|
|
2790
|
+
// ---- Helpers
|
|
2791
|
+
|
|
2792
|
+
function asBindingPattern(node: Node | undefined): BindingPattern | undefined {
|
|
2793
|
+
if (node === undefined) return undefined;
|
|
2794
|
+
if (node instanceof BindingPattern) return node as BindingPattern;
|
|
2795
|
+
return undefined;
|
|
2796
|
+
}
|
|
2797
|
+
|
|
2798
|
+
function typesAreSameReference(a: Type, b: Type): boolean {
|
|
2799
|
+
return a === b || (a.symbol !== undefined && a.symbol === b.symbol) || (a.alias !== undefined && a.alias === b.alias);
|
|
2800
|
+
}
|
|
2801
|
+
|
|
2802
|
+
/** Internal names other than late-bound and private names. */
|
|
2803
|
+
function isReservedMemberName(name: string): boolean {
|
|
2804
|
+
return (
|
|
2805
|
+
name.length >= 2 && name.charCodeAt(0) === 0xfffe && name.charCodeAt(1) !== 0x40 && name.charCodeAt(1) !== 0x23
|
|
2806
|
+
);
|
|
2807
|
+
}
|
|
2808
|
+
|
|
2809
|
+
function isPrivateIdentifierSymbol(symbol: Symbol): boolean {
|
|
2810
|
+
return symbol.name.startsWith('#');
|
|
2811
|
+
}
|
|
2812
|
+
|
|
2813
|
+
function isClassInstanceSide(c: Checker, t: Type): boolean {
|
|
2814
|
+
const symbol = t.symbol;
|
|
2815
|
+
return (
|
|
2816
|
+
symbol !== undefined &&
|
|
2817
|
+
(symbol.flags & SymbolFlags.Class) !== 0 &&
|
|
2818
|
+
(t === getDeclaredTypeOfClassOrInterface(c, symbol) ||
|
|
2819
|
+
((t.flags & TypeFlags.Object) !== 0 && (t.objectFlags & ObjectFlags.IsClassInstanceClone) !== 0))
|
|
2820
|
+
);
|
|
2821
|
+
}
|
|
2822
|
+
|
|
2823
|
+
function getTypeAliasForTypeLiteral(c: Checker, t: Type): Symbol | undefined {
|
|
2824
|
+
const symbol = t.symbol;
|
|
2825
|
+
if (symbol === undefined || (symbol.flags & SymbolFlags.TypeLiteral) === 0 || declarationCount(symbol) === 0)
|
|
2826
|
+
return undefined;
|
|
2827
|
+
let node = symbol.declaration!.parent;
|
|
2828
|
+
while (node !== undefined && node.kind === SyntaxKind.ParenthesizedType) node = node.parent;
|
|
2829
|
+
if (node !== undefined && node.kind === SyntaxKind.TypeAliasDeclaration) return getSymbolOfDeclaration(c, node);
|
|
2830
|
+
return undefined;
|
|
2831
|
+
}
|
|
2832
|
+
|
|
2833
|
+
/** A copy of `t`, whose members are `resolved`, without its abstract construct signatures. */
|
|
2834
|
+
function getResolvedTypeWithoutAbstractConstructSignatures(c: Checker, t: Type, resolved: StructuredType): Type {
|
|
2835
|
+
if (resolved.constructSignatures.length === 0) return t;
|
|
2836
|
+
const side = membersHolder(c, t);
|
|
2837
|
+
if (side.objectTypeWithoutAbstractConstructSignatures !== undefined)
|
|
2838
|
+
return side.objectTypeWithoutAbstractConstructSignatures;
|
|
2839
|
+
const constructSignatures = resolved.constructSignatures.filter((s) => (s.flags & SignatureFlags.Abstract) === 0);
|
|
2840
|
+
if (constructSignatures.length === resolved.constructSignatures.length) {
|
|
2841
|
+
side.objectTypeWithoutAbstractConstructSignatures = t;
|
|
2842
|
+
return t;
|
|
2843
|
+
}
|
|
2844
|
+
const copy = newAnonymousType(c, t.symbol);
|
|
2845
|
+
const copied = membersHolder(c, copy);
|
|
2846
|
+
copied.objectFlags |= ObjectFlags.MembersResolved;
|
|
2847
|
+
copied.members = resolved.members;
|
|
2848
|
+
copied.properties = resolved.properties;
|
|
2849
|
+
copied.callSignatures = resolved.callSignatures;
|
|
2850
|
+
copied.constructSignatures = constructSignatures;
|
|
2851
|
+
copied.indexInfos = resolved.indexInfos;
|
|
2852
|
+
side.objectTypeWithoutAbstractConstructSignatures = copy;
|
|
2853
|
+
sideOf(c, copy).objectTypeWithoutAbstractConstructSignatures = copy;
|
|
2854
|
+
return copy;
|
|
2855
|
+
}
|
|
2856
|
+
|
|
2857
|
+
function getNameFromIndexInfo(info: IndexInfo): string {
|
|
2858
|
+
const declaration = info.declaration;
|
|
2859
|
+
if (declaration === undefined) return 'x';
|
|
2860
|
+
const parameters = getParameters(declaration);
|
|
2861
|
+
const name = parameters !== undefined && parameters.nodes.length > 0 ? getName(parameters.nodes[0]!) : undefined;
|
|
2862
|
+
return name === undefined ? 'x' : declarationNameToString(getSourceFileOfNode(name), name);
|
|
2863
|
+
}
|
|
2864
|
+
|
|
2865
|
+
function hasAccessorKeyword(node: Node): boolean {
|
|
2866
|
+
const modifiers = getModifiers(node);
|
|
2867
|
+
return modifiers !== undefined && modifiers.nodes.some((m) => m.kind === SyntaxKind.AccessorKeyword);
|
|
2868
|
+
}
|
|
2869
|
+
|
|
2870
|
+
function getEffectiveConstraint(typeParameter: Node): Node | undefined {
|
|
2871
|
+
return typeParameter instanceof TypeParameterDeclaration ? typeParameter.constraint : undefined;
|
|
2872
|
+
}
|
|
2873
|
+
|
|
2874
|
+
function getTypeParameterModifiers(tp: Type): ModifierFlags {
|
|
2875
|
+
let flags = ModifierFlags.None;
|
|
2876
|
+
if (tp.symbol !== undefined) for (const d of getDeclarations(tp.symbol)) flags |= getCombinedModifierFlags(d);
|
|
2877
|
+
return flags & (ModifierFlags.In | ModifierFlags.Out | ModifierFlags.Const);
|
|
2878
|
+
}
|
|
2879
|
+
|
|
2880
|
+
function getEffectiveParameterDeclaration(symbol: Symbol): Node | undefined {
|
|
2881
|
+
const parameter = getDeclarationOfKind(symbol, SyntaxKind.Parameter);
|
|
2882
|
+
if (parameter !== undefined) return parameter;
|
|
2883
|
+
if ((symbol.flags & SymbolFlags.Transient) === 0) return getDeclarationOfKind(symbol, SyntaxKind.JSDocParameterTag);
|
|
2884
|
+
return undefined;
|
|
2885
|
+
}
|
|
2886
|
+
|
|
2887
|
+
function isPropertyAccessEntityNameExpression(node: Node): boolean {
|
|
2888
|
+
return node.kind === SyntaxKind.PropertyAccessExpression && isEntityNameExpression(node, false);
|
|
2889
|
+
}
|
|
2890
|
+
|
|
2891
|
+
/** Whether an existing type reference node can stand for `t`: JS `Foo` meaning `Foo<any>` can't. */
|
|
2892
|
+
export function canReuseExistingJSTypeNode(b: NodeBuilder, existing: Node, t: Type): boolean {
|
|
2893
|
+
const c = b.c;
|
|
2894
|
+
if (getIntendedTypeFromJSDocTypeReference(c, existing) !== undefined) return false;
|
|
2895
|
+
if ((t.objectFlags & ObjectFlags.Reference) === 0 || !(existing instanceof TypeReferenceNode)) return true;
|
|
2896
|
+
getTypeFromTypeNode(c, existing);
|
|
2897
|
+
const symbol = c.resolvedSymbols.get(existing.id);
|
|
2898
|
+
if (symbol === undefined) return true;
|
|
2899
|
+
const existingTarget = getDeclaredTypeOfSymbol(c, symbol);
|
|
2900
|
+
if (existingTarget !== (t as TypeReference).target) return true;
|
|
2901
|
+
const written = existing.typeArguments === undefined ? 0 : existing.typeArguments.nodes.length;
|
|
2902
|
+
return written >= getMinTypeArgumentCount(c, (existingTarget as InterfaceType).typeParameters());
|
|
2903
|
+
}
|
|
2904
|
+
|
|
2905
|
+
/** Copies the emit nodes of `original`'s descendants to the same nodes of its deep clone `clone`. */
|
|
2906
|
+
function copyEmitNodes(context: EmitContext, clone: Node, original: Node, isRoot: boolean): void {
|
|
2907
|
+
// The root is a copy, which gets the original's emit node without its comments when the
|
|
2908
|
+
// original is set; the descendants stand for the original's own.
|
|
2909
|
+
if (!isRoot) context.copyEmitNode(clone, original);
|
|
2910
|
+
const cloneChildren = new ChildCollector();
|
|
2911
|
+
clone.forEachChild(cloneChildren);
|
|
2912
|
+
const originalChildren = new ChildCollector();
|
|
2913
|
+
original.forEachChild(originalChildren);
|
|
2914
|
+
const count = Math.min(cloneChildren.nodes.length, originalChildren.nodes.length);
|
|
2915
|
+
for (let i = 0; i < count; i++) copyEmitNodes(context, cloneChildren.nodes[i]!, originalChildren.nodes[i]!, false);
|
|
2916
|
+
}
|
|
2917
|
+
|
|
2918
|
+
class ChildCollector extends NodeVisitor {
|
|
2919
|
+
readonly nodes: Node[] = [];
|
|
2920
|
+
readonly lists: NodeList[] = [];
|
|
2921
|
+
|
|
2922
|
+
visitNode(node: Node): boolean {
|
|
2923
|
+
this.nodes.push(node);
|
|
2924
|
+
return false;
|
|
2925
|
+
}
|
|
2926
|
+
|
|
2927
|
+
visitList(list: NodeList): boolean {
|
|
2928
|
+
this.lists.push(list);
|
|
2929
|
+
return super.visitList(list);
|
|
2930
|
+
}
|
|
2931
|
+
}
|
|
2932
|
+
|
|
2933
|
+
/** Sets each node of `original`'s subtree as the original of its copy in `clone`, keeping trailing commas. */
|
|
2934
|
+
function linkClones(context: EmitContext, clone: Node, original: Node): void {
|
|
2935
|
+
if (context.getOriginal(clone) === undefined) context.setOriginal(clone, original);
|
|
2936
|
+
const cloneChildren = new ChildCollector();
|
|
2937
|
+
clone.forEachChild(cloneChildren);
|
|
2938
|
+
const originalChildren = new ChildCollector();
|
|
2939
|
+
original.forEachChild(originalChildren);
|
|
2940
|
+
const lists = Math.min(cloneChildren.lists.length, originalChildren.lists.length);
|
|
2941
|
+
for (let i = 0; i < lists; i++) {
|
|
2942
|
+
const list = cloneChildren.lists[i]!;
|
|
2943
|
+
if (originalChildren.lists[i]!.hasTrailingComma() && list.nodes.length > 0) {
|
|
2944
|
+
const last = list.nodes[list.nodes.length - 1]!;
|
|
2945
|
+
last.pos = -2;
|
|
2946
|
+
last.end = -2;
|
|
2947
|
+
}
|
|
2948
|
+
}
|
|
2949
|
+
const count = Math.min(cloneChildren.nodes.length, originalChildren.nodes.length);
|
|
2950
|
+
for (let i = 0; i < count; i++) linkClones(context, cloneChildren.nodes[i]!, originalChildren.nodes[i]!);
|
|
2951
|
+
}
|
|
2952
|
+
|
|
2953
|
+
/** A copy of a binding name without initializers, written on one line. */
|
|
2954
|
+
function cloneBindingName(b: NodeBuilder, node: Node): Node {
|
|
2955
|
+
node.forEachChild(new ComputedNameTracker(b));
|
|
2956
|
+
const clone = node.deepClone();
|
|
2957
|
+
removeBindingInitializers(clone);
|
|
2958
|
+
clearPositions(clone);
|
|
2959
|
+
keepTrailingCommas(clone, node);
|
|
2960
|
+
b.context.setEmitFlags(clone, EmitFlags.SingleLine | EmitFlags.NoAsciiEscaping);
|
|
2961
|
+
return clone;
|
|
2962
|
+
}
|
|
2963
|
+
|
|
2964
|
+
/**
|
|
2965
|
+
* Marks the element lists of `clone` that have a trailing comma in `original`, which the printer
|
|
2966
|
+
* keeps: tsgo's copy keeps the lists' positions.
|
|
2967
|
+
*/
|
|
2968
|
+
function keepTrailingCommas(clone: Node, original: Node): void {
|
|
2969
|
+
if (!(clone instanceof BindingPattern) || !(original instanceof BindingPattern)) return;
|
|
2970
|
+
// As tsgo's deep clone: a last element ending before the list's end.
|
|
2971
|
+
if (original.elements.hasTrailingComma() && clone.elements.nodes.length > 0) {
|
|
2972
|
+
const last = clone.elements.nodes[clone.elements.nodes.length - 1]!;
|
|
2973
|
+
last.pos = -2;
|
|
2974
|
+
last.end = -2;
|
|
2975
|
+
}
|
|
2976
|
+
const elements = clone.elements.nodes;
|
|
2977
|
+
const originals = original.elements.nodes;
|
|
2978
|
+
for (let i = 0; i < elements.length && i < originals.length; i++) {
|
|
2979
|
+
const element = elements[i]!;
|
|
2980
|
+
const originalElement = originals[i]!;
|
|
2981
|
+
if (
|
|
2982
|
+
element instanceof BindingElement &&
|
|
2983
|
+
originalElement instanceof BindingElement &&
|
|
2984
|
+
element.name !== undefined &&
|
|
2985
|
+
originalElement.name !== undefined
|
|
2986
|
+
)
|
|
2987
|
+
keepTrailingCommas(element.name, originalElement.name);
|
|
2988
|
+
}
|
|
2989
|
+
}
|
|
2990
|
+
|
|
2991
|
+
function removeBindingInitializers(node: Node): void {
|
|
2992
|
+
if (node instanceof BindingPattern) {
|
|
2993
|
+
for (const e of node.elements.nodes) removeBindingInitializers(e);
|
|
2994
|
+
return;
|
|
2995
|
+
}
|
|
2996
|
+
if (node instanceof BindingElement) {
|
|
2997
|
+
node.initializer = undefined;
|
|
2998
|
+
if (node.name !== undefined) removeBindingInitializers(node.name);
|
|
2999
|
+
}
|
|
3000
|
+
}
|
|
3001
|
+
|
|
3002
|
+
/** Tracks the late-bound computed names of a binding name, which the copy writes. */
|
|
3003
|
+
class ComputedNameTracker extends NodeVisitor {
|
|
3004
|
+
readonly b: NodeBuilder;
|
|
3005
|
+
|
|
3006
|
+
constructor(b: NodeBuilder) {
|
|
3007
|
+
super();
|
|
3008
|
+
this.b = b;
|
|
3009
|
+
}
|
|
3010
|
+
|
|
3011
|
+
visitNode(node: Node): boolean {
|
|
3012
|
+
if (node.kind === SyntaxKind.ComputedPropertyName && isLateBindableName(this.b.c, node))
|
|
3013
|
+
this.b.trackComputedName(getExpression(node)!, this.b.enclosingDeclaration);
|
|
3014
|
+
return node.forEachChild(this);
|
|
3015
|
+
}
|
|
3016
|
+
}
|
|
3017
|
+
|
|
3018
|
+
class PositionClearer extends NodeVisitor {
|
|
3019
|
+
visitNode(node: Node): boolean {
|
|
3020
|
+
clearPositions(node);
|
|
3021
|
+
return false;
|
|
3022
|
+
}
|
|
3023
|
+
|
|
3024
|
+
// A list keeping its range would print a trailing comma after its now unpositioned nodes.
|
|
3025
|
+
visitList(list: NodeList): boolean {
|
|
3026
|
+
list.pos = -1;
|
|
3027
|
+
list.end = -1;
|
|
3028
|
+
for (const node of list.nodes) clearPositions(node);
|
|
3029
|
+
return false;
|
|
3030
|
+
}
|
|
3031
|
+
}
|
|
3032
|
+
|
|
3033
|
+
/** Drops the positions of a copied subtree; its flags stay those of the original, as in tsgo. */
|
|
3034
|
+
export function clearPositions(node: Node): void {
|
|
3035
|
+
node.pos = -1;
|
|
3036
|
+
node.end = -1;
|
|
3037
|
+
node.forEachChild(new PositionClearer());
|
|
3038
|
+
}
|
|
3039
|
+
|
|
3040
|
+
/** Whether a parameter is optional in its signature, as tsgo's `isOptionalParameter`. */
|
|
3041
|
+
export function isOptionalParameter(c: Checker, node: Node): boolean {
|
|
3042
|
+
if (!(node instanceof ParameterDeclaration)) return false;
|
|
3043
|
+
if (node.questionToken !== undefined) return true;
|
|
3044
|
+
const parent = node.parent!;
|
|
3045
|
+
const parameters = getParameters(parent);
|
|
3046
|
+
const index = parameters === undefined ? -1 : parameters.nodes.indexOf(node);
|
|
3047
|
+
if (node.initializer !== undefined) {
|
|
3048
|
+
const signature = getSignatureFromDeclaration(c, parent);
|
|
3049
|
+
// Without treating `void` parameters as optional, as grammar checks use this.
|
|
3050
|
+
let minArgumentCount = signature.minArgumentCount;
|
|
3051
|
+
if (signature.hasRestParameter()) {
|
|
3052
|
+
const restType = getTypeOfSymbol(c, signature.parameters[signature.parameters.length - 1]!);
|
|
3053
|
+
if (isTupleType(restType)) {
|
|
3054
|
+
const tuple = (restType as TypeReference).target as TupleType;
|
|
3055
|
+
let requiredCount = tuple.fixedLength;
|
|
3056
|
+
for (let i = 0; i < tuple.elementInfos.length; i++)
|
|
3057
|
+
if ((tuple.elementInfos[i].flags & ElementFlags.Required) === 0) {
|
|
3058
|
+
requiredCount = i;
|
|
3059
|
+
break;
|
|
3060
|
+
}
|
|
3061
|
+
if (requiredCount > 0) minArgumentCount = signature.parameters.length - 1 + requiredCount;
|
|
3062
|
+
}
|
|
3063
|
+
}
|
|
3064
|
+
return index >= minArgumentCount;
|
|
3065
|
+
}
|
|
3066
|
+
const iife = getImmediatelyInvokedFunctionExpression(parent);
|
|
3067
|
+
if (iife !== undefined)
|
|
3068
|
+
return (
|
|
3069
|
+
node.type === undefined && node.dotDotDotToken === undefined && index >= getEffectiveCallArguments(c, iife).length
|
|
3070
|
+
);
|
|
3071
|
+
return false;
|
|
3072
|
+
}
|
|
3073
|
+
|
|
3074
|
+
/** Whether a parameter's written type needs `| undefined`: initialized before a required parameter. */
|
|
3075
|
+
export function requiresAddingImplicitUndefined(
|
|
3076
|
+
c: Checker,
|
|
3077
|
+
parameter: Node,
|
|
3078
|
+
enclosingDeclaration: Node | undefined,
|
|
3079
|
+
): boolean {
|
|
3080
|
+
if (!(parameter instanceof ParameterDeclaration) || (parameter.flags & NodeFlags.Synthesized) !== 0) return false;
|
|
3081
|
+
const isPropertyParameter = hasSyntacticModifier(parameter, ModifierFlags.ParameterPropertyModifier);
|
|
3082
|
+
let required = false;
|
|
3083
|
+
if (c.strictNullChecks && !isOptionalParameter(c, parameter) && parameter.initializer !== undefined)
|
|
3084
|
+
required =
|
|
3085
|
+
!isPropertyParameter || (enclosingDeclaration !== undefined && isFunctionLikeDeclaration(enclosingDeclaration));
|
|
3086
|
+
const optionalProperty =
|
|
3087
|
+
c.strictNullChecks &&
|
|
3088
|
+
isOptionalParameter(c, parameter) &&
|
|
3089
|
+
parameter.initializer === undefined &&
|
|
3090
|
+
isPropertyParameter;
|
|
3091
|
+
if (!required && !optionalProperty) return false;
|
|
3092
|
+
const typeNode = parameter.type;
|
|
3093
|
+
if (typeNode === undefined) return true;
|
|
3094
|
+
const t = getTypeFromTypeNode(c, typeNode);
|
|
3095
|
+
return !isErrorType(c, t) && !containsUndefinedType(c, t);
|
|
3096
|
+
}
|
|
3097
|
+
|
|
3098
|
+
function containsUndefinedType(c: Checker, t: Type): boolean {
|
|
3099
|
+
const types = (t.flags & TypeFlags.Union) !== 0 ? (t as UnionType).types : [t];
|
|
3100
|
+
return (types[0].flags & TypeFlags.Undefined) !== 0;
|
|
3101
|
+
}
|
|
3102
|
+
|
|
3103
|
+
function isFunctionLikeDeclaration(node: Node): boolean {
|
|
3104
|
+
switch (node.kind) {
|
|
3105
|
+
case SyntaxKind.FunctionDeclaration:
|
|
3106
|
+
case SyntaxKind.MethodDeclaration:
|
|
3107
|
+
case SyntaxKind.Constructor:
|
|
3108
|
+
case SyntaxKind.GetAccessor:
|
|
3109
|
+
case SyntaxKind.SetAccessor:
|
|
3110
|
+
case SyntaxKind.FunctionExpression:
|
|
3111
|
+
case SyntaxKind.ArrowFunction:
|
|
3112
|
+
return true;
|
|
3113
|
+
}
|
|
3114
|
+
return false;
|
|
3115
|
+
}
|
|
3116
|
+
|
|
3117
|
+
/** Whether the first identifier of an entity name can be named from `enclosingDeclaration`. */
|
|
3118
|
+
export function isEntityNameVisible(
|
|
3119
|
+
c: Checker,
|
|
3120
|
+
entityName: Node,
|
|
3121
|
+
enclosingDeclaration: Node,
|
|
3122
|
+
shouldComputeAliasesToMakeVisible: boolean = false,
|
|
3123
|
+
): SymbolAccessibilityResult {
|
|
3124
|
+
if ((entityName.flags & NodeFlags.Synthesized) !== 0)
|
|
3125
|
+
return new SymbolAccessibilityResult(SymbolAccessibility.NotAccessible, [], '', undefined, '');
|
|
3126
|
+
const meaning = getMeaningOfEntityNameReference(entityName);
|
|
3127
|
+
const firstIdentifier = getFirstIdentifier(entityName);
|
|
3128
|
+
const text = getText(firstIdentifier);
|
|
3129
|
+
const symbol = resolveName(c, enclosingDeclaration, text, meaning, undefined, false, false);
|
|
3130
|
+
if (symbol !== undefined && (symbol.flags & SymbolFlags.TypeParameter) !== 0 && (meaning & SymbolFlags.Type) !== 0)
|
|
3131
|
+
return accessible([]);
|
|
3132
|
+
if (symbol === undefined && firstIdentifier.kind === SyntaxKind.ThisKeyword) {
|
|
3133
|
+
const container = getThisContainer(firstIdentifier, false, false);
|
|
3134
|
+
const sym = container === undefined ? undefined : getSymbolOfDeclaration(c, container);
|
|
3135
|
+
if (
|
|
3136
|
+
isSymbolAccessible(c, sym, enclosingDeclaration, meaning, false).accessibility === SymbolAccessibility.Accessible
|
|
3137
|
+
)
|
|
3138
|
+
return accessible([]);
|
|
3139
|
+
}
|
|
3140
|
+
if (symbol === undefined)
|
|
3141
|
+
return new SymbolAccessibilityResult(SymbolAccessibility.NotResolved, [], text, firstIdentifier, '');
|
|
3142
|
+
const visible = hasVisibleDeclarations(c, symbol, shouldComputeAliasesToMakeVisible);
|
|
3143
|
+
if (visible !== undefined) return visible;
|
|
3144
|
+
return new SymbolAccessibilityResult(SymbolAccessibility.NotAccessible, [], text, firstIdentifier, '');
|
|
3145
|
+
}
|
|
3146
|
+
|
|
3147
|
+
/**
|
|
3148
|
+
* The parameter lists of a signature with a tuple rest parameter spread into parameters; one
|
|
3149
|
+
* list per member of a union of tuples unless `skipUnionExpanding`.
|
|
3150
|
+
*/
|
|
3151
|
+
export function getExpandedParameters(c: Checker, signature: Signature, skipUnionExpanding: boolean): Symbol[][] {
|
|
3152
|
+
if (signature.hasRestParameter()) {
|
|
3153
|
+
const restIndex = signature.parameters.length - 1;
|
|
3154
|
+
const restSymbol = signature.parameters[restIndex]!;
|
|
3155
|
+
const restType = getTypeOfSymbol(c, restSymbol);
|
|
3156
|
+
if (isTupleType(restType))
|
|
3157
|
+
return [expandSignatureParametersWithTupleMembers(c, signature, restType, restIndex, restSymbol)];
|
|
3158
|
+
if (!skipUnionExpanding && (restType.flags & TypeFlags.Union) !== 0) {
|
|
3159
|
+
const types = (restType as UnionType).types;
|
|
3160
|
+
for (const t of types) if (!isTupleType(t)) return [signature.parameters];
|
|
3161
|
+
const lists: Symbol[][] = [];
|
|
3162
|
+
for (const t of types)
|
|
3163
|
+
lists.push(expandSignatureParametersWithTupleMembers(c, signature, t, restIndex, restSymbol));
|
|
3164
|
+
return lists;
|
|
3165
|
+
}
|
|
3166
|
+
}
|
|
3167
|
+
return [signature.parameters];
|
|
3168
|
+
}
|
|
3169
|
+
|
|
3170
|
+
function expandSignatureParametersWithTupleMembers(
|
|
3171
|
+
c: Checker,
|
|
3172
|
+
signature: Signature,
|
|
3173
|
+
restType: Type,
|
|
3174
|
+
restIndex: number,
|
|
3175
|
+
restSymbol: Symbol,
|
|
3176
|
+
): Symbol[] {
|
|
3177
|
+
const elementTypes = getTypeArguments(c, restType);
|
|
3178
|
+
const tuple = (restType as TypeReference).target as TupleType;
|
|
3179
|
+
const names = getUniqueAssociatedNamesFromTupleType(c, tuple, restSymbol);
|
|
3180
|
+
const result = signature.parameters.slice(0, restIndex);
|
|
3181
|
+
for (let i = 0; i < elementTypes.length; i++) {
|
|
3182
|
+
const flags = tuple.elementInfos[i]!.flags;
|
|
3183
|
+
let checkFlags = CheckFlags.None;
|
|
3184
|
+
if ((flags & ElementFlags.Variable) !== 0) checkFlags = CheckFlags.RestParameter;
|
|
3185
|
+
else if ((flags & ElementFlags.Optional) !== 0) checkFlags = CheckFlags.OptionalParameter;
|
|
3186
|
+
const symbol = c.newSymbolWithCheckFlags(SymbolFlags.FunctionScopedVariable, names[i]!, checkFlags);
|
|
3187
|
+
const elementType = elementTypes[i]!;
|
|
3188
|
+
c.symbolTypes.set(
|
|
3189
|
+
getSymbolId(symbol),
|
|
3190
|
+
(flags & ElementFlags.Rest) !== 0 ? createArrayType(c, elementType) : elementType,
|
|
3191
|
+
);
|
|
3192
|
+
result.push(symbol);
|
|
3193
|
+
}
|
|
3194
|
+
return result;
|
|
3195
|
+
}
|
|
3196
|
+
|
|
3197
|
+
function getUniqueAssociatedNamesFromTupleType(c: Checker, tuple: TupleType, restSymbol: Symbol): string[] {
|
|
3198
|
+
const names: string[] = [];
|
|
3199
|
+
for (let i = 0; i < tuple.elementInfos.length; i++) {
|
|
3200
|
+
const info = tuple.elementInfos[i]!;
|
|
3201
|
+
names.push(getTupleElementLabel(c, info.flags, info.labeledDeclaration, restSymbol, i));
|
|
3202
|
+
}
|
|
3203
|
+
if (names.length === 0) return names;
|
|
3204
|
+
const duplicates: number[] = [];
|
|
3205
|
+
const uniqueNames = new Set<string>();
|
|
3206
|
+
for (let i = 0; i < names.length; i++) {
|
|
3207
|
+
const name = names[i]!;
|
|
3208
|
+
if (uniqueNames.has(name)) duplicates.push(i);
|
|
3209
|
+
else uniqueNames.add(name);
|
|
3210
|
+
}
|
|
3211
|
+
const counters = new Map<string, number>();
|
|
3212
|
+
for (const i of duplicates) {
|
|
3213
|
+
const base = names[i]!;
|
|
3214
|
+
let counter = counters.get(base) ?? 1;
|
|
3215
|
+
let name: string;
|
|
3216
|
+
for (;;) {
|
|
3217
|
+
name = base + '_' + counter;
|
|
3218
|
+
if (uniqueNames.has(name)) {
|
|
3219
|
+
counter++;
|
|
3220
|
+
continue;
|
|
3221
|
+
}
|
|
3222
|
+
uniqueNames.add(name);
|
|
3223
|
+
break;
|
|
3224
|
+
}
|
|
3225
|
+
names[i] = name;
|
|
3226
|
+
counters.set(name, counter + 1);
|
|
3227
|
+
}
|
|
3228
|
+
return names;
|
|
3229
|
+
}
|
|
3230
|
+
|
|
3231
|
+
/** The name a tuple element gets as a parameter. */
|
|
3232
|
+
export function getTupleElementLabel(
|
|
3233
|
+
c: Checker,
|
|
3234
|
+
flags: ElementFlags,
|
|
3235
|
+
labeledDeclaration: Node | undefined,
|
|
3236
|
+
restSymbol: Symbol | undefined,
|
|
3237
|
+
index: number,
|
|
3238
|
+
): string {
|
|
3239
|
+
if (labeledDeclaration !== undefined) return getText(getName(labeledDeclaration)!);
|
|
3240
|
+
if (restSymbol !== undefined && restSymbol.valueDeclaration instanceof ParameterDeclaration)
|
|
3241
|
+
return getTupleElementLabelFromBindingElement(restSymbol.valueDeclaration, index, flags);
|
|
3242
|
+
return (restSymbol !== undefined ? restSymbol.name : 'arg') + '_' + index;
|
|
3243
|
+
}
|
|
3244
|
+
|
|
3245
|
+
function getTupleElementLabelFromBindingElement(node: Node, index: number, elementFlags: ElementFlags): string {
|
|
3246
|
+
const name = getName(node);
|
|
3247
|
+
const hasDotDotDot =
|
|
3248
|
+
(node instanceof ParameterDeclaration && node.dotDotDotToken !== undefined) ||
|
|
3249
|
+
(node instanceof BindingElement && node.dotDotDotToken !== undefined);
|
|
3250
|
+
if (name !== undefined) {
|
|
3251
|
+
if (name.kind === SyntaxKind.Identifier) {
|
|
3252
|
+
const text = getText(name);
|
|
3253
|
+
// `(...[x, y, ...z]: [number, number, ...number[]])` keeps `z`; fixed elements of a rest get suffixes.
|
|
3254
|
+
if (hasDotDotDot) return (elementFlags & ElementFlags.Variable) !== 0 ? text : text + '_' + index;
|
|
3255
|
+
return (elementFlags & ElementFlags.Fixed) !== 0 ? text : text + '_n';
|
|
3256
|
+
}
|
|
3257
|
+
if (name.kind === SyntaxKind.ArrayBindingPattern && hasDotDotDot) {
|
|
3258
|
+
const elements = (name as BindingPattern).elements.nodes;
|
|
3259
|
+
const lastElement = elements.length > 0 ? elements[elements.length - 1]! : undefined;
|
|
3260
|
+
const lastIsRest = lastElement instanceof BindingElement && lastElement.dotDotDotToken !== undefined;
|
|
3261
|
+
const elementCount = elements.length - (lastIsRest ? 1 : 0);
|
|
3262
|
+
if (index < elementCount) {
|
|
3263
|
+
const element = elements[index]!;
|
|
3264
|
+
if (element instanceof BindingElement)
|
|
3265
|
+
return getTupleElementLabelFromBindingElement(element, index, elementFlags);
|
|
3266
|
+
} else if (lastIsRest)
|
|
3267
|
+
return getTupleElementLabelFromBindingElement(lastElement!, index - elementCount, elementFlags);
|
|
3268
|
+
}
|
|
3269
|
+
}
|
|
3270
|
+
return 'arg_' + index;
|
|
3271
|
+
}
|
|
3272
|
+
|
|
3273
|
+
// ---- Entry points
|
|
3274
|
+
|
|
3275
|
+
/**
|
|
3276
|
+
* The type node TypeScript would write for `type`. As in tsgo, the builder has a pseudochecker, so types
|
|
3277
|
+
* of declarations are written from what the source wrote where that denotes the type.
|
|
3278
|
+
*/
|
|
3279
|
+
export function typeToTypeNode(
|
|
3280
|
+
c: Checker,
|
|
3281
|
+
type: Type,
|
|
3282
|
+
enclosingDeclaration: Node | undefined,
|
|
3283
|
+
flags: number,
|
|
3284
|
+
internalFlags: NodeBuilderInternalFlags = NodeBuilderInternalFlags.None,
|
|
3285
|
+
tracker: SymbolTracker | undefined = undefined,
|
|
3286
|
+
): Node | undefined {
|
|
3287
|
+
const b = new NodeBuilder(c, enclosingDeclaration, flags, internalFlags, tracker);
|
|
3288
|
+
b.pseudo = newPseudoChecker(c);
|
|
3289
|
+
return b.finish(b.typeToTypeNode(type));
|
|
3290
|
+
}
|
|
3291
|
+
|
|
3292
|
+
/** The declaration of kind `kind` TypeScript would write for `signature`, with a pseudochecker as `typeToTypeNode`. */
|
|
3293
|
+
export function signatureToSignatureDeclaration(
|
|
3294
|
+
c: Checker,
|
|
3295
|
+
signature: Signature,
|
|
3296
|
+
kind: SyntaxKind,
|
|
3297
|
+
enclosingDeclaration: Node | undefined,
|
|
3298
|
+
flags: number,
|
|
3299
|
+
internalFlags: NodeBuilderInternalFlags = NodeBuilderInternalFlags.None,
|
|
3300
|
+
tracker: SymbolTracker | undefined = undefined,
|
|
3301
|
+
): Node | undefined {
|
|
3302
|
+
const b = new NodeBuilder(c, enclosingDeclaration, flags, internalFlags, tracker);
|
|
3303
|
+
b.pseudo = newPseudoChecker(c);
|
|
3304
|
+
return b.finish(b.signatureToSignatureDeclaration(signature, kind, undefined));
|
|
3305
|
+
}
|
|
3306
|
+
|
|
3307
|
+
/** The type format flags that are node builder flags. */
|
|
3308
|
+
function toNodeBuilderFlags(typeFormatFlags: number): NodeBuilderFlags {
|
|
3309
|
+
return (
|
|
3310
|
+
typeFormatFlags &
|
|
3311
|
+
(NodeBuilderFlags.NoTruncation |
|
|
3312
|
+
NodeBuilderFlags.WriteArrayAsGenericType |
|
|
3313
|
+
NodeBuilderFlags.GenerateNamesForShadowedTypeParams |
|
|
3314
|
+
NodeBuilderFlags.UseStructuralFallback |
|
|
3315
|
+
NodeBuilderFlags.WriteTypeArgumentsOfSignature |
|
|
3316
|
+
NodeBuilderFlags.UseFullyQualifiedType |
|
|
3317
|
+
NodeBuilderFlags.SuppressAnyReturnType |
|
|
3318
|
+
NodeBuilderFlags.MultilineObjectLiterals |
|
|
3319
|
+
NodeBuilderFlags.WriteClassExpressionAsTypeLiteral |
|
|
3320
|
+
NodeBuilderFlags.UseTypeOfFunction |
|
|
3321
|
+
NodeBuilderFlags.OmitParameterModifiers |
|
|
3322
|
+
NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope |
|
|
3323
|
+
NodeBuilderFlags.AllowUniqueESSymbolType |
|
|
3324
|
+
NodeBuilderFlags.InTypeAlias |
|
|
3325
|
+
NodeBuilderFlags.UseInstantiationExpressions |
|
|
3326
|
+
NodeBuilderFlags.UseSingleQuotesForStringLiteralType |
|
|
3327
|
+
NodeBuilderFlags.NoTypeReduction |
|
|
3328
|
+
NodeBuilderFlags.OmitThisParameter)
|
|
3329
|
+
);
|
|
3330
|
+
}
|
|
3331
|
+
|
|
3332
|
+
/**
|
|
3333
|
+
* `type` as text, printed from its type node as tsgo's `TypeToStringEx` does; `typeFormatFlags`
|
|
3334
|
+
* are `TypeFormatFlags`. Undefined if the builder fails.
|
|
3335
|
+
*/
|
|
3336
|
+
export function typeToStringFromTypeNode(
|
|
3337
|
+
c: Checker,
|
|
3338
|
+
type: Type,
|
|
3339
|
+
enclosingDeclaration: Node | undefined,
|
|
3340
|
+
typeFormatFlags: number,
|
|
3341
|
+
): string | undefined {
|
|
3342
|
+
// Serializing can resolve members and report diagnostics needing serialization in turn.
|
|
3343
|
+
if (c.serializationLevel >= maxSerializationLevel) return '?';
|
|
3344
|
+
const multiline = (typeFormatFlags & NodeBuilderFlags.MultilineObjectLiterals) !== 0;
|
|
3345
|
+
const noTruncation =
|
|
3346
|
+
c.compilerOptions.noErrorTruncation === true || (typeFormatFlags & NodeBuilderFlags.NoTruncation) !== 0;
|
|
3347
|
+
let flags = toNodeBuilderFlags(typeFormatFlags) | NodeBuilderFlags.IgnoreErrors;
|
|
3348
|
+
if (noTruncation) flags |= NodeBuilderFlags.NoTruncation;
|
|
3349
|
+
const b = new NodeBuilder(c, enclosingDeclaration, flags, NodeBuilderInternalFlags.None, undefined);
|
|
3350
|
+
b.pseudo = newPseudoChecker(c);
|
|
3351
|
+
c.serializationLevel++;
|
|
3352
|
+
const typeNode = b.finish(b.typeToTypeNode(type));
|
|
3353
|
+
c.serializationLevel--;
|
|
3354
|
+
if (typeNode === undefined) return undefined;
|
|
3355
|
+
const options = new PrinterOptions();
|
|
3356
|
+
// Only the unresolved type keeps its comment, a hint that it isn't a plain `any`.
|
|
3357
|
+
options.removeComments = type !== c.unresolvedType;
|
|
3358
|
+
options.newLine = multiline ? '\n' : '';
|
|
3359
|
+
const writer = new TextWriter(options.newLine, 0);
|
|
3360
|
+
const sourceFile = enclosingDeclaration === undefined ? undefined : getSourceFileOfNode(enclosingDeclaration);
|
|
3361
|
+
new Printer(options, b.context).write(typeNode, sourceFile, writer, undefined);
|
|
3362
|
+
const result = writer.getText();
|
|
3363
|
+
const maxLength = noTruncation ? noTruncationMaximumTruncationLength * 2 : defaultMaximumTruncationLength * 2;
|
|
3364
|
+
if (result.length >= maxLength) return result.substring(0, maxLength - 3) + '...';
|
|
3365
|
+
return result;
|
|
3366
|
+
}
|
|
3367
|
+
|
|
3368
|
+
/** The index signature TypeScript would write for `info`. */
|
|
3369
|
+
export function indexInfoToIndexSignatureDeclaration(
|
|
3370
|
+
c: Checker,
|
|
3371
|
+
info: IndexInfo,
|
|
3372
|
+
enclosingDeclaration: Node | undefined,
|
|
3373
|
+
flags: number,
|
|
3374
|
+
tracker: SymbolTracker | undefined,
|
|
3375
|
+
): Node | undefined {
|
|
3376
|
+
const b = new NodeBuilder(c, enclosingDeclaration, flags, NodeBuilderInternalFlags.None, tracker);
|
|
3377
|
+
return b.finish(b.indexInfoToIndexSignatureDeclaration(info, undefined));
|
|
3378
|
+
}
|
|
3379
|
+
|
|
3380
|
+
/** The type parameter declaration TypeScript would write for `parameter`. */
|
|
3381
|
+
export function typeParameterToDeclaration(
|
|
3382
|
+
c: Checker,
|
|
3383
|
+
parameter: Type,
|
|
3384
|
+
enclosingDeclaration: Node | undefined,
|
|
3385
|
+
flags: number,
|
|
3386
|
+
tracker: SymbolTracker | undefined,
|
|
3387
|
+
): Node | undefined {
|
|
3388
|
+
const b = new NodeBuilder(c, enclosingDeclaration, flags, NodeBuilderInternalFlags.None, tracker);
|
|
3389
|
+
return b.finish(b.typeParameterToDeclaration(parameter));
|
|
3390
|
+
}
|
|
3391
|
+
|
|
3392
|
+
/** The type predicate node TypeScript would write for `predicate`. */
|
|
3393
|
+
export function typePredicateToTypePredicateNode(
|
|
3394
|
+
c: Checker,
|
|
3395
|
+
predicate: TypePredicate,
|
|
3396
|
+
enclosingDeclaration: Node | undefined,
|
|
3397
|
+
flags: number,
|
|
3398
|
+
tracker: SymbolTracker | undefined,
|
|
3399
|
+
): Node | undefined {
|
|
3400
|
+
const b = new NodeBuilder(c, enclosingDeclaration, flags, NodeBuilderInternalFlags.None, tracker);
|
|
3401
|
+
return b.finish(b.typePredicateToTypePredicateNode(predicate));
|
|
3402
|
+
}
|
|
3403
|
+
|
|
3404
|
+
/** The entity name TypeScript would write for `symbol` with `meaning`. */
|
|
3405
|
+
export function symbolToEntityName(
|
|
3406
|
+
c: Checker,
|
|
3407
|
+
symbol: Symbol,
|
|
3408
|
+
meaning: SymbolFlags,
|
|
3409
|
+
enclosingDeclaration: Node | undefined,
|
|
3410
|
+
flags: number,
|
|
3411
|
+
tracker: SymbolTracker | undefined,
|
|
3412
|
+
): Node | undefined {
|
|
3413
|
+
const b = new NodeBuilder(c, enclosingDeclaration, flags, NodeBuilderInternalFlags.None, tracker);
|
|
3414
|
+
return b.finish(symbolToName(b, symbol, meaning, false));
|
|
3415
|
+
}
|
|
3416
|
+
|
|
3417
|
+
/** The expression TypeScript would write for `symbol` with `meaning`. */
|
|
3418
|
+
export function symbolToExpressionNode(
|
|
3419
|
+
c: Checker,
|
|
3420
|
+
symbol: Symbol,
|
|
3421
|
+
meaning: SymbolFlags,
|
|
3422
|
+
enclosingDeclaration: Node | undefined,
|
|
3423
|
+
flags: number,
|
|
3424
|
+
tracker: SymbolTracker | undefined,
|
|
3425
|
+
): Node | undefined {
|
|
3426
|
+
const b = new NodeBuilder(c, enclosingDeclaration, flags, NodeBuilderInternalFlags.None, tracker);
|
|
3427
|
+
return b.finish(symbolToExpression(b, symbol, meaning));
|
|
3428
|
+
}
|
|
3429
|
+
|
|
3430
|
+
/** The UTF-8 offset of UTF-16 offset `pos` in `text`. */
|
|
3431
|
+
function utf8Offset(text: string, pos: number): number {
|
|
3432
|
+
return pos <= 0 ? pos : utf8Length(text.slice(0, pos));
|
|
3433
|
+
}
|